转:
synchronized void setA() throws Exception{ Thread.sleep(1000); setB(); } synchronized void setB() throws Exception{ Thread.sleep(1000); }
区别
static synchronized方法是类锁,synchronized方法是对象锁
synchronized相当于 this.synchronized,static synchronized相当于Something.synchronized
pulbic class Test(){ public synchronized void A(){} public synchronized void B(){} public static synchronized void cA(){} public static synchronized void cB(){} }
新建两个实例,x和y
1 x.A()与x.B() 2 x.A()与y.A() 3 x.cA()与y.cB() 4 x.A()与Test.cA()
四种情况哪组方法何以被多个以上线程同时访问?
Lock是一个接口
public interface Lock { void lock(); void lockInterruptibly() throws InterruptedException; boolean tryLock(); boolean tryLock(long time, TimeUnit unit) throws InterruptedException; void unlock(); Condition newCondition(); }
lock()
、tryLock()
、tryLock(long time, TimeUnit unit)
和lockInterruptibly()
是用来获取锁的。unLock()
方法是用来释放锁的。lock()
平常使用得最多的一个方法,就是用来获取锁。如果锁已被其他线程获取,则进行等待。
使用Lock必须在try{}catch{}
块中进行,并且将释放锁的操作放在finally
块中进行,以保证锁一定被被释放,防止死锁的发生。
Lock lock = ...; lock.lock(); try{ //处理任务 }catch(Exception ex){ }finally{ lock.unlock(); //释放锁 }
tryLock()
tryLock()
有返回值的,它表示用来尝试获取锁,如果获取成功,则返回true,如果锁已被其他线程获取,则返回false。
这个方法会立即返回,在拿不到锁时也不会一直在那等待。
Lock lock = ...; if(lock.tryLock()) { try{ //处理任务 }catch(Exception ex){ }finally{ lock.unlock(); //释放锁 } }else { //如果不能获取锁,则直接做其他事情 }
tryLock(long time, TimeUnit unit)
此方法在拿不到锁时会等待一定的时间,在时间期限之内如果还拿不到锁,就返回false。如果如果一开始拿到锁或者在等待期间内拿到了锁,则返回true。
lockInterruptibly()
方法比较特殊,当通过这个方法去获取锁时,如果线程正在等待获取锁,则这个线程能够响应中断,即中断线程的等待状态。也就使说,当两个线程同时通过lock.lockInterruptibly()
想获取某个锁时,假若此时线程A获取到了锁,而线程B还在等待,那么对线程B调用threadB.interrupt()方法中断线程B的等待过程。
lockInterruptibly()
当通过lockInterruptibly()方法获取某个锁时,如果不能获取到,只有进行等待的情况下,是可以响应中断的。
而用synchronized修饰的话,当一个线程处于等待某个锁的状态,是无法被中断的,只有一直等待下去。
当一个线程获取了锁之后,是不会被interrupt()方法中断的。单独调用interrupt()方法不能中断正在运行过程中的线程,只能中断阻塞过程中的线程。
lockInterruptibly()
的声明中抛出了异常,所以lock.lockInterruptibly()
必须放在try块中或者在调用lockInterruptibly()
的方法外声明抛出InterruptedException。
public void method() throws InterruptedException { lock.lockInterruptibly(); try { //..... } finally { lock.unlock(); } }
类别 | synchronized | Lock |
---|---|---|
存在层次 | Java的关键字,在jvm层面上 | 是一个接口 |
锁的释放 | 以获取锁的线程执行完同步代码,释放锁 线程执行发生异常,jvm会让线程释放锁 |
在finally中必须释放锁,不然容易造成线程死锁 |
锁的获取 | 死等 | 有多个锁获取的方式,可以尝试获得锁,线程可以不用死等 |
锁状态 | 无法判断 | 可以判断 |
锁类型 | 可重入 不可中断 非公平 |
可重入 可判断 可公平(两者皆可) |
性能 | 少量同步时更好 | 大量同步时更好 |
synchronized:在需要同步的对象中加入此控制,synchronized可以加在方法上,也可以加在特定代码块中,括号中表示需要锁的对象。
public synchronized void Test(){} synchronized(temp){ // 操作 }
Lock:需要显示指定起始位置和终止位置。前文已经有示例这里不再举例。
两者在一般情况下没有什么区别,但在非常复杂的同步应用中,应该使用Lock,例如:
某个线程在等待一个锁的控制权的这段时间需要中断
需要分开处理一些wait/notify,JUC里面的Condition,能够实现精准唤醒
需要公平锁功能
转: