java 并发 同步_Java的并发(二) 同步

同步问题

在多线程程序中,因为各线程访问时机的不可控,在对共享资源的访问中很可能会产生不一致性,产生错误的结果。这就是线程安全问题。

这时候就需要对互斥资源(临界资源)进行访问的同步,一般都是通过对互斥资源进行序列化访问来解决的。一般来说,是通过在访问互斥资源前加锁,访问结束后释放锁,来实现的。

在java中,有两中方式实现锁,synchronized 关键字和与锁有关的工具类 Lock。

synchronized关键字

是java为了提供对锁的支持而设置的,其机制是使用对象内部的锁。一般来说,每个对象都会有一个锁,每个类也有一个类锁。

synchronized关键字的使用:

一般有两种方式:同步方法和同步块。

同步方法,synchronized修饰方法,那么线程访问该方法时会先获取该方法所属的实例对象的锁(如果获取不到如已经有其它线程持有该对象的锁了,则会阻塞等待,并且不能被中断),方法执行结束后自动释放该对象的锁。

还有几个需要注意的地方:如果该方法执行过程中抛出异常,则jvm会自动释放该对象的锁。对象的锁是重入锁(递归锁),后面会提到的Lock也是可重入锁。

也可用于同步块,有时候方法内部只有一部分需要同步,因此可以使用synchronized同步块,如下:

synchronized(someObject){

...

}

Lock

Lock代表了Java语言中通过特定类型的类来支持锁机制的方式,另外Lock也是java.util.concurrent.Locks包下的一个接口,主要包含如下方法:

void lock();//获取锁,阻塞

boolean tryLock();//尝试获取锁,会立即返回

boolean tryLock(Time.Unit sometime);//等待一端时间再返回

void lockInperruptibly();//阻塞,但是会响应中断

void unlock();//释放锁

ReentranLock是jdk中Lock接口的唯一实现,从名字上看就知道是一个可重入锁。相对于synchronized关键字,Lock方式使用起来更加灵活:可以实现非阻塞的方式,可以设置是否会响应中断。

另外,需要补充的一点,synchronized方式获取的锁是非公平锁,不可改变。ReentranLock默认也是非公平锁,但是可以通过new ReentranLock(boolean)来设置是否是公平锁。

公平锁:对等待队列里面的线程,谁获得锁。公平锁使等待最久的线程获得锁。

此外还有读写锁:ReadWriteLock,也是一个接口,该接口声明了对文件的读、写操作分开获取锁的方式,

Lock readLock();//获取读锁

Lock writeLock();//获取写锁

这样可以允许多个线程同时读(提高了效率),不允许有读也有写以及同时写。

ReentrantReadWriteLock实现了ReadWriteLock接口,对多个线程同时读的情况,相对于声明方法为synchronized的方式,可以显著提高效率。

Locks包中包含的类还有:ReentrantReadWriteLock.ReadLock、ReentrantReadWriteLock.WriteLock等。

锁的种类:

可重入锁

根据上面的讨论,synchronized关键字使用的对象内部锁、Lock锁都是可重入(递归)的。什么叫可重入锁,有没有不可重入锁呢?

可重入性就是说如果一个线程已经获取了某对象的锁,在运行的过程中如果还需要访问该对象的其它同步方法或者同步块,这时候是否需要重新申请锁。如果不需要重新申请就是可重入锁,否则就是不可重入的。

因为锁操作的粒度是线程,而不是方法调用,因此对于再次进入同步代码的线程,讲道理应该是可以使用之前获取的锁。为什么需要可重入锁呢?简单解释下,因为线程已经获得了锁,当在同步代码内部再次调用新的同步代码块时,如果需要重新申请锁,就会产生死锁。

也有不可重入锁的。

Linux下的pthread_mutex_t锁是默认是非递归的。可以通过设置PTHREAD_MUTEX_RECURSIVE属性,将pthread_mutex_t锁设置为递归锁。

如何实现可重入和不可重入锁?

可重入锁大概是:对一个对象的锁,维持一个当前持有该锁的线程记录以及锁请求计数。第一次锁被某线程获取时,记录该线程编号,并将锁计数+1。对新的锁请求,如果线程为持有锁的线程,则将锁计数+1,然后直接进入同步代码,离开时-1. 当锁计数为0时,代表锁被释放。

可中断锁:

在获取锁的过程中是否可以响应中断。

公平锁

读写锁

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值