Lock 和 synchronized的区别
1、线程生命周期
线程总共有5大状态
-
新建状态:新建线程对象,并没有调用start()方法之前
-
就绪状态:调用start()方法之后线程就进入就绪状态,但是并不是说只要调用start()方法线程就马上变为当前线程,在变为当前线程之前都是为就绪状态。值得一提的是,线程在睡眠和挂起中恢复的时候也会进入就绪状态哦。
-
运行状态:线程被设置为当前线程,开始执行run()方法。就是线程进入运行状态
-
阻塞状态:线程被暂停,比如说调用sleep()方法后线程就进入阻塞状态
-
死亡状态:线程执行结束
锁类型
-
lock():获取锁,如果锁被暂用则一直等待
-
unlock():释放锁
-
tryLock(): 注意返回类型是boolean,如果获取锁的时候锁被占用就返回false,否则返回true
-
tryLock(long time, TimeUnit unit):比起tryLock()就是给了一个时间期限,保证等待参数时间
-
lockInterruptibly():用该锁的获得方式,如果线程在获取锁的阶段进入了等待,那么可以中断此线程,先去做别的事
package cn.xiang.thread.lock; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; /** * lock锁学习demo * 总结: * 1、使用lock.lock()方法可以将对象锁定。同时必须在finally将锁释放lock.unlock(),否则其他对象获取不了该锁。 * 2、如果是线程内新定义的对象,那么有无锁都会异步执行,并不同步。 * @author 向宁 *日期:2018年4月11日 *时间:下午3:26:06 * */ public class LockDemo01 { /** * 创建锁 */ private Lock lock = new ReentrantLock(); /** * 需要同步执行的方法 * @param thread * @throws InterruptedException */ public void lockMethod(){ System.out.println("还没开始锁定"); lock.lock(); Thread thread = Thread.currentThread(); System.out.println("我是" + thread.getName() + "!正在使用锁"); try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); }finally{ lock.unlock(); } } public static void main(String[] args) { final LockDemo01 lockDemo = new LockDemo01(); Thread t1 = new Thread(){ @Override public void run(){ lockDemo.lockMethod(); } }; Thread t2 = new Thread(){ @Override public void run(){ lockDemo.lockMethod(); } }; t1.start(); t2.start(); } }
结果如下:
package cn.xiang.thread.lock; /** * lock.tryLock() * 可if判断该代码是否被锁定。如果被锁定,则不执行。 * lock.tryLock(time, unit) * 给一个等待时间,等待时间过后,如果锁定被释放,则可以直接进入。如果等待时间已过,还不释放。则直接执行else * */ import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; public class LockDemo02 { private Lock lock = new ReentrantLock(); /** * 需要同步的方法 */ public void lockMethod(){ try { System.out.println("开始执行方法"); if (lock.tryLock(1, TimeUnit.SECONDS)) { //如果当前已经被锁定 try { System.out.println("我是线程:" + Thread.currentThread().getName() + "!我已经拿到了该锁!"); Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); }finally{ lock.unlock(); } }else{ System.out.println("我是线程:" + Thread.currentThread().getName() + "!我没有拿到该锁,就不要了!"); } } catch (InterruptedException e) { e.printStackTrace(); } } public static void main(String[] args) { final LockDemo02 lockDemo = new LockDemo02(); Thread t1 = new Thread(){ @Override public void run(){ lockDemo.lockMethod(); } }; Thread t2 = new Thread(){ @Override public void run(){ lockDemo.lockMethod(); } }; Thread t3 = new Thread(){ @Override public void run(){ lockDemo.lockMethod(); } }; t1.start(); t2.start(); try { Thread.sleep(3000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } t3.start(); } }
结果如下:
以下是一个简单的死锁
package cn.xiang.thread; public class ThreadDeadLock03 { public static void main(String[] args) { LockDemo04 lock = new LockDemo04(false); new Thread(lock).start(); new Thread(lock).start(); } } class LockDemo04 implements Runnable{ private boolean flag; private Object obj1 = new Object(); private Object obj2 = new Object(); public LockDemo04(boolean flag){ this.flag = flag; } @Override public void run() { flag = !flag; try { if(flag){ synchronized(obj1){ System.out.println("已经拿到obj1的对象锁"); Thread.sleep(1000); System.out.println("准备拿obj2的对象锁"); synchronized(obj2){ System.out.println("已经拿到obj2的对象锁,表示没有发生死锁"); } } }else{ synchronized(obj2){ System.out.println("已经拿到obj2的对象锁"); Thread.sleep(1000); System.out.println("准备拿obj1的对象锁"); synchronized(obj1){ System.out.println("已经拿到obj1的对象锁,表示没有发生死锁!"); } } } } catch (Exception e) { // TODO: handle exception } } }
效果: