一、synchronized同步方法
论:“线程安全”与“非线程安全”是多线程的经典问题。synchronized()方法就是解决非线程安全的。
1、方法内的变量为线程安全
public void addI(String username) { try { int num = 0; \\方法内的变量为线程安全 if (username.equals("a")) { num = 100; System.out.println("a set over!"); Thread.sleep(2000); } else { num = 200; System.out.println("b set over!"); } System.out.println(username + " num=" + num); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } }
2、实例变量非线程安全
public class HasSelfPrivateNum { private int num = 0; \\实例变量非线程安全 public void addI(String username) { try { if (username.equals("a")) { num = 100; System.out.println("a set over!"); Thread.sleep(2000); } else { num = 200; System.out.println("b set over!"); } System.out.println(username + " num=" + num); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
解决方法: 方法前加synchronized关键字。
public class HasSelfPrivateNum { private int num = 0; synchronized public void addI(String username) { .............. } }
3、多个对象多个锁
HasSelfPrivateNum.java
public class HasSelfPrivateNum { private int num = 0; synchronized public void addI(String username) { try { if (username.equals("a")) { num = 100; System.out.println("a set over!"); Thread.sleep(2000); } else { num = 200; System.out.println("b set over!"); } System.out.println(username + " num=" + num); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
ThreadA
public class ThreadA extends Thread {
private HasSelfPrivateNum numRef;
public ThreadA(HasSelfPrivateNum numRef) {
super();
this.numRef = numRef;
}
@Override
public void run() {
super.run();
numRef.addI("a");
}
}
ThreadB
public class ThreadB extends Thread { private HasSelfPrivateNum numRef; public ThreadB(HasSelfPrivateNum numRef) { super(); this.numRef = numRef; } @Override public void run() { super.run(); numRef.addI("b"); } }
RUN
public class Run { public static void main(String[] args) { HasSelfPrivateNum numRef1 = new HasSelfPrivateNum(); HasSelfPrivateNum numRef2 = new HasSelfPrivateNum(); ThreadA athread = new ThreadA(numRef1); athread.start(); ThreadB bthread = new ThreadB(numRef2); bthread.start(); } }
结果:创建了2个业务实例,产生2个锁,所以运行结果是异步的。同步为synchronized 异步:asynchronized
4、synchronized 锁重入
当一个线程得到一个对象锁时,再次请求该对象锁时是可以再次得到该对象的锁的。继承关系也可重入锁。
当一个线程执行发生异常时,其持有的锁会自动释放。
同步不具有继承性。的在子类方法中添加synchronized的关键字。
public class HasSelfPrivateNum { synchronized public void service1() { System.out.println("service1"); service2(); } synchronized public void service2() { System.out.println("service2"); service3(); } synchronized public void service3() { System.out.println("service3"); } }