多线程基础(四)---线程同步

当多个线程访问同一共享资源的时候会出现线程安全性问题

常见的问题举例就是买票问题

如何解决线程之间的安全性问题

synchronized和关键字

三种使用方式

  • 修饰代码块
  • 修饰方法
  • 修饰静态方法

1、修饰代码块

synchronized(对象/类.class) {
}

可以是任意的非null的对象,但是必须保证多线程锁的是一个对象

2、修饰方法
对this加锁
3、修饰静态方法
对类.class加锁

加锁的原理:
多个线程访问一个共享数据的时候,只有一个线程可以获取到对象锁,因为一个对象只有一把锁,一个线程获取到锁之后,其他线程只有等待锁释放才能获取锁。保证了数据的同步性。

线程死锁

多个线程相互持有锁,想要获取对方的锁,形成一个闭环。生活中两个人通过获取到一根筷子,都不想释放手中的筷子,都想要获取对方的筷子就都吃不成饭

线程死锁的条件:
1、互斥条件,一个资源只能被一个线程使用
2、请求和等待,请求资源的时候阻塞,不主动释放已经占用的资源
3、不可剥夺,资源只能主动释放,不能被其他线程抢占
4、循环依赖,形成死锁的时候,多个线程形成一个资源链

如何避免死锁:
破坏请求和等待:当申请资源的时候,一次性申请所需要的所有资源
破坏不可剥夺:当申请资源的时候长时间陷入阻塞,主动释放占用的资源
破坏循环等待:按照一定顺序申请资源,避免形成资源链

ReentrantLock

使用try finaly来进行lock和unlock

synchronized和ReentrantLock的区别

1、基础的使用
前者是加代码块/方法,后者使用try finally进行加锁。解锁
2、是否主动释放锁
前者进入代码块就主动加锁,离开代码块的时候主动释放锁。后者需要主动释放锁
3、锁的类型不同
前者是非公平锁,后者可以是公平锁也可以是非公平锁
4、响应中断
前者不能响应中断,出现死锁的时候会一直等待下去。
后者能响应中断,获取不到锁后响应中断释放所占用的锁
5、实现原理
前者的JVM层面的监视器实现的,后者是基于AQS程序级别的API实现的

posted @ 2024-10-09 10:43  goodguyly  阅读(5)  评论(0)    收藏  举报