Java多线程与并发编程 | 多线程的同步机制

296 阅读2分钟

这是我参与8月更文挑战的第21天,活动详情查看:8月更文挑战

前言

synchronized(同步锁)关键字的作用就是利用特定的对象设置一个锁lock,在多线程并发访问时,同时只允许一个线程可以获得这个锁,执行特定的代码。执行后释放锁,继续由其它线程争抢。

Synchronize的使用场景

可以使用在以下三种场景,对应不同的锁对象

  • synchronize代码块:任意对象即可 synchronize(object){}
  • synchronize方法:this当前对象 synchronize(this){}
  • synchronize静态方法:当前类的字节码对象 synchronize(Object.calss){}

线程的五种状态

  • 1. 新建(new)
  • 2. 就绪(ready)
  • 3. 运行中(running)
  • 4. 阻塞(blocked)
  • 5. 死亡(dead)

image.png

死锁的产生

死锁是多线程情况下最严重的问题,出现死锁的原因是,多个线程对公共资源进行操作时,彼此不释放自己占有的资源,而去试图操作其它线程的资源,从而形成了交叉引用,就会产生死锁

例子 image.png

线程A任务是向AB两个文件写入信息,操作步骤:先获取文件A,写入,再获取文件B,写入,然后释放文件A文件B
线程B任务也是是向BA两个文件写入信息,操作步骤:先获取文件B,写入,再获取文件A,写入,然后释放文件A文件B
注意:这里区别是一个先写文件A,一个先写文件B
这里就出现了公共资源交叉引用的问题,当两个线程同时执行

  • 线程A占有了文件A,这个时候线程B占有了文件B;
  • 线程A文件A中写入信息后想去获取文件B,但是文件B线程B占用着,这个时候线程A占用着文件A,等待线程B释放文件B,但是反过来,线程B占用着文件B,等待着线程A释放文件A,这时候双方都持有对方需要的资源,但是又不释放自己当前占有的,互相等待,出现了死锁的情况。

解决死锁的建议

  • 尽量减少公共资源的引用,用完马上释放
  • 减少synchronize使用,采用“副本”方式替代