1、加锁不正确导致数据不一致:m1执行过程中,m2(未加synchronized)可以执行,因为m2不用获得锁就可以执行
1 public class TT implements Runnable { 2 int b = 100; 3 4 public synchronized void m1() throws Exception { 5 b = 1000; 6 System.out.println("in m1() before sleep,b="+b); 7 Thread.sleep(5000); 8 System.out.println("in m1() after sleep,b="+b); 9 } 10 11 public void m2() { 12 //public synchronized void m2() throws Exception { 13 b = 199; 14 System.out.println("in m2(),b="+b); 15 } 16 17 public void run() { 18 try { 19 m1(); 20 } catch (Exception e) { 21 e.printStackTrace(); 22 } 23 } 24 25 public static void main(String[] args) throws Exception { 26 TT tt = new TT(); 27 System.out.println("in main() just after new TT(),b=" + tt.b); 28 Thread t = new Thread(tt); 29 t.start(); 30 31 Thread.sleep(1000); //为了让m1能够执行b=1000的赋值 32 tt.m2(); // 主线程执行m2 33 34 System.out.println("in main() last,b=" + tt.b); 35 } 36 }
结果:
D:聚划算技术部编程练习TestThreadSync>java TT
in main() just after new TT(),b=100
in m1() before sleep,b=1000
in m2(),b=199
in main() last,b=199
in m1() after sleep,b=199 //main线程先于t线程结束吗?
说明:锁定当前对象 只是针对synchronized 这段话,另外的线程完全有可能访问没有锁定的方法(即不带synchronized 的方法)
问题:要保证对资源b的正确访问,需要考虑所有访问b的所有方法,是否需要加同步:加了同步效率可能变低、不加同步可能会出现数据不一致
问题:main线程先于t线程结束吗?
解答:会,main方法即使执行完最后的语句,JVM也不会结束该程序,要等到主线程中的所有其它线程都结束之后,才结束该JAVA应用程序
2、解决上述访问资源b,数据不一致的问题:把所有访问b的方法加锁,m1执行过程,m2一定执行不了,执行m2时必须要得到当前对象的锁才能执行
1 public class TT implements Runnable { 2 int b = 100; 3 4 public synchronized void m1() throws Exception { 5 b = 1000; 6 System.out.println("in m1() before sleep,b="+b); 7 Thread.sleep(5000); 8 System.out.println("in m1() after sleep,b="+b); 9 } 10 11 public synchronized void m2() { 12 //public synchronized void m2() throws Exception { 13 b = 199; 14 System.out.println("in m2(),b="+b); 15 } 16 17 public void run() { 18 try { 19 m1(); 20 } catch (Exception e) { 21 e.printStackTrace(); 22 } 23 } 24 25 public static void main(String[] args) throws Exception { 26 TT tt = new TT(); 27 System.out.println("in main() just after new TT(),b=" + tt.b); 28 Thread t = new Thread(tt); 29 t.start(); 30 31 Thread.sleep(1000); //为了让m1能够执行b=1000的赋值 32 tt.m2(); 33 34 System.out.println("in main() last,b=" + tt.b); 35 } 36 }
结果:
D:聚划算技术部编程练习TestThreadSync>java TT
in main() just after new TT(),b=100
in m1() before sleep,b=1000
in m1() after sleep,b=1000 //m1执行完了才会执行m2
in m2(),b=199
in main() last,b=199
举例:
如何加锁:——设定同步对象时较麻烦
数据库中的某一个记录,可以改、也可以读,一般情况下哪个方法应该加锁?
(1)读:允许多个线程同时读
(2)改:要加synchronized ,不允许两个线程同时改