一、改变了锁对象
package com.lanyun.hadoop2;/** * 锁对象的改变问题 * */public class ChangeLock { private String lock = "lock"; private void method() { synchronized (lock) { try { System.out.println("当前线程 : " + Thread.currentThread().getName() + "开始"); lock = "change lock"; Thread.sleep(2000); System.out.println("当前线程 : " + Thread.currentThread().getName() + "结束"); } catch (InterruptedException e) { e.printStackTrace(); } } } public static void main(String[] args) { final ChangeLock changeLock = new ChangeLock(); Thread t1 = new Thread(new Runnable() { public void run() { changeLock.method(); } }, "t1"); Thread t2 = new Thread(new Runnable() { public void run() { changeLock.method(); } }, "t2"); t1.start(); try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } t2.start(); }}
本来打算让t1先执行,t1执行完成之后t2再执行,但是t1线程将锁对象改变了,所以可以说t1线程获取的是字符串“lock”的对象锁,t2线程获取的是字符串“change lock”的对象锁。
二、死锁问题
package com.lanyun.hadoop2;/** * 死锁问题,在设计程序时就应该避免双方相互持有对方的锁的情况 * */public class DeadLock implements Runnable{ private String tag; private static Object lock1 = new Object(); private static Object lock2 = new Object(); public void setTag(String tag){ this.tag = tag; } public void run() { if(tag.equals("a")){ synchronized (lock1) { try { System.out.println("当前线程 : " + Thread.currentThread().getName() + " 进入lock1执行"); Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } synchronized (lock2) { System.out.println("当前线程 : " + Thread.currentThread().getName() + " 进入lock2执行"); } } } if(tag.equals("b")){ synchronized (lock2) { try { System.out.println("当前线程 : " + Thread.currentThread().getName() + " 进入lock2执行"); Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } synchronized (lock1) { System.out.println("当前线程 : " + Thread.currentThread().getName() + " 进入lock1执行"); } } } } public static void main(String[] args) { DeadLock d1 = new DeadLock(); d1.setTag("a"); DeadLock d2 = new DeadLock(); d2.setTag("b"); Thread t1 = new Thread(d1, "t1"); Thread t2 = new Thread(d2, "t2"); t1.start(); try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } t2.start(); }}
三、修改锁对象的属性
package com.lanyun.hadoop2;/** * 同一对象属性的修改不会影响锁的情况 * */public class ModifyLock { private String name ; private int age ; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public synchronized void changeAttributte(String name, int age) { try { System.out.println("当前线程 : " + Thread.currentThread().getName() + " 开始"); this.setName(name); this.setAge(age); System.out.println("当前线程 : " + Thread.currentThread().getName() + " 修改对象内容为: " + this.getName() + ", " + this.getAge()); Thread.sleep(2000); System.out.println("当前线程 : " + Thread.currentThread().getName() + " 结束"); } catch (InterruptedException e) { e.printStackTrace(); } } public static void main(String[] args) { final ModifyLock modifyLock = new ModifyLock(); Thread t1 = new Thread(new Runnable() { public void run() { modifyLock.changeAttributte("张三", 20); } },"t1"); Thread t2 = new Thread(new Runnable() { public void run() { modifyLock.changeAttributte("李四", 21); } },"t2"); t1.start(); try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } t2.start(); }}
四、对象锁与类所
package com.lanyun.hadoop2;/** * 使用synchronized代码块加锁,比较灵活 * */public class ObjectLock { public void method1(){ synchronized (this) { //对象锁 try { System.out.println("do method1.."); Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } } } public void method2(){ //类锁 synchronized (ObjectLock.class) { try { System.out.println("do method2.."); Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } } } private Object lock = new Object(); public void method3(){ //任何对象锁 synchronized (lock) { try { System.out.println("do method3.."); Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } } } public static void main(String[] args) { final ObjectLock objLock = new ObjectLock(); Thread t1 = new Thread(new Runnable() { public void run() { objLock.method1(); } }); Thread t2 = new Thread(new Runnable() { public void run() { objLock.method2(); } }); Thread t3 = new Thread(new Runnable() { public void run() { objLock.method3(); } }); t1.start(); t2.start(); t3.start(); }}
五、使用synchronized代码块减小锁的粒度,提高性能
package com.lanyun.hadoop2;/** * 使用synchronized代码块减小锁的粒度,提高性能 * */public class Optimize { public void doLongTimeTask(){ try { System.out.println("当前线程开始:" + Thread.currentThread().getName() + ", 正在执行一个较长时间的业务操作,其内容不需要同步"); Thread.sleep(2000); synchronized(this){ System.out.println("当前线程:" + Thread.currentThread().getName() + ", 执行同步代码块,对其同步变量进行操作"); Thread.sleep(1000); } System.out.println("当前线程结束:" + Thread.currentThread().getName() + ", 执行完毕"); } catch (InterruptedException e) { e.printStackTrace(); } } public static void main(String[] args) { final Optimize otz = new Optimize(); Thread t1 = new Thread(new Runnable() { public void run() { otz.doLongTimeTask(); } },"t1"); Thread t2 = new Thread(new Runnable() { public void run() { otz.doLongTimeTask(); } },"t2"); t1.start(); t2.start(); }}
六、避免使用字符串对象来做锁
package com.lanyun.hadoop2;/** * synchronized代码块对字符串的锁,注意String常量池的缓存功能 * */public class StringLock { public void method() { //new String("字符串常量") synchronized ("字符串常量") { try { while(true){ System.out.println("当前线程 : " + Thread.currentThread().getName() + "开始"); Thread.sleep(1000); System.out.println("当前线程 : " + Thread.currentThread().getName() + "结束"); } } catch (InterruptedException e) { e.printStackTrace(); } } } public static void main(String[] args) { final StringLock stringLock = new StringLock(); Thread t1 = new Thread(new Runnable() { public void run() { stringLock.method(); } },"t1"); Thread t2 = new Thread(new Runnable() { public void run() { stringLock.method(); } },"t2"); t1.start(); t2.start(); }}