线程安全 - >线程同步

1.线程安全问题:

多个线程同时操作同一个共享资源的时候可能会出现业务安全问题,成为线程安全问题。

2.取钱案例:

需求:小明和小红是一对夫妻,他们有一个共同的账户,余额是10万元。

如果小明和小红同时来取钱,而且2人都要取钱10万元,可能出现什么问题呢?

假设小明的进程先执行,先小明进程判断余额是否足够,后小红进程判断余额是否足够,余额足够,先小明进程在账户中吐出10w元,更新余额,然后小红进程在账户中吐出10w元,更新余额,最后小明取钱后剩余0.0元,小红取钱后剩余-10w元。

1.线程安全问题出现的原因?

1.存在多线程并发。

2.同时访问共享资源。

3.存在修改共享资源。

3.线程同步  -> 为了解决线程安全问题

1.取钱案例出现问题的原因?

多个线程同时执行,发现账户都是够钱的。

2.如何才能保证线程安全呢?

让多个线程实现先后依次访问共享资源,这样就解决了安全问题。

3.线程同步的核心思想

加锁:把共享资源进行加锁,每次只能一个线程进入访问完毕以后解锁,然后其他线程才能进来。

方式一:同步代码块

作用:把出现线程安全问题的核心代码给上锁。

原理:每次只能一个线程进入,执行完毕后自动解锁,其他线程才可以进来执行。

1.锁对象要求

理论上:锁对象只要对于当前同时执行的线程来说是同一个对象即可。

2.锁对象用任意唯一的对象好不好呢?

不好,会影响其他无关线程的执行。

3.锁对象的规范要求:

① 规范上:建议使用共享资源作为锁对象。

② 对于实例方法建议使用this作为锁对象。

③ 对于静态方法建议使用字节码(类名.class) 对象作为锁对象。

4.代码:

总结:

1.同步代码块是如何实现线程安全的?

① 对出现问题的核心代码使用synchronized进行加锁。

② 每次只能一个线程占锁进入访问。

2.同步代码块的同步锁对象有什么要求?

① 对于实例方法建议使用this作为锁对象。

② 对于静态方法建议使用字节码(类名.class)对象作为锁对象。

方式二:同步方法

作用:把出现线程安全问题的核心方法给上锁。

原理:每次只能一个线程进入,执行完毕以后自动解锁,其他线程才可以进来执行。

1.同步方法底层原理:

① 同步方法其实底层也是有隐式锁对象的 ,只是锁的范围是整个方法代码。

② 如果方法是实例方法:同步方法默认用 this作为的锁对象。但是代码要高度面向对象!

③ 如果方法是静态方法 :同步方法默认用类名.class作为的锁对象。

3.同步代码块好还是同步方法好一点?

同步代码块锁的范围更小,同步方法锁的范围更大。

方式三:Lock锁

为了更清晰的表达如何加锁和释放锁,JDK5以后提供了一个新的锁对象Lock,更加灵活、方便。

Lock实现提供比使用synchronized方法和语句可以获得更广泛的锁定操作。

Lock是接口不能直接实例化,这里采用它的实现类ReentrantLock来构建Lock锁对象。

看完以上有补充和纠正,欢迎各位在评论区评论,谢谢大家。

经验分享 程序员 微信小程序 职场和发展