synchronized使用之基本原则:
synchronized可以锁方法,也可以锁代码片段,但要实现互斥的基本就是在想要互斥的代码上加”同一把锁“,也就是同一个对象,也就是用==判断等于true的对象
下面看一个例子:
Work.java 真正做事情的类
1 package com.yzl; 2 3 public class Work { 4 /** 5 * 未同步的 6 * @param name 7 */ 8 public void noSynwrite(String name){ 9 for(int i=0; i<name.length(); i++){ 10 System.out.print(name.charAt(i)); 11 if(i == (name.length()-1)){ 12 System.out.print(" "); 13 } 14 } 15 } 16 17 /** 18 * 使用同步块,并使用Work的实例对象做为锁 19 * 此方法的同步需保证是调用该方法的work对象是同一个 20 * @param name 21 */ 22 public void write1(String name){ 23 synchronized (this) { 24 for(int i=0; i<name.length(); i++){ 25 System.out.print(name.charAt(i)); 26 if(i == (name.length()-1)){ 27 System.out.print(" "); 28 } 29 } 30 } 31 } 32 33 /** 34 * 使用同步块,并使用Work的字节码做为锁 35 * @param name 36 */ 37 public void write1WithStatic(String name){ 38 synchronized (Work.class) { 39 for(int i=0; i<name.length(); i++){ 40 System.out.print(name.charAt(i)); 41 if(i == (name.length()-1)){ 42 System.out.print(" "); 43 } 44 } 45 } 46 } 47 48 /** 49 * 使用同步的方法,锁对象为ork的实例对象 50 * 此方法的同步需保证是调用该方法的work对象是同一个 51 * @param name 52 */ 53 public synchronized void write2(String name){ 54 for(int i=0; i<name.length(); i++){ 55 System.out.print(name.charAt(i)); 56 if(i == (name.length()-1)){ 57 System.out.print(" "); 58 } 59 } 60 } 61 62 /** 63 * 静态方法的同步方法,同步的对象是对象的字节码,也就是Work.class 64 * 如果要与上面的方法一起使用并保持互斥,则可以把write1的锁对象this改成Work.class 65 * @param name 66 */ 67 public synchronized static void write3(String name){ 68 for(int i=0; i<name.length(); i++){ 69 System.out.print(name.charAt(i)); 70 if(i == (name.length()-1)){ 71 System.out.print(" "); 72 } 73 } 74 } 75 }
测试类ThreadPart_2.java
1 package com.yzl; 2 3 /** 4 * 传统的线程互斥 5 * 原理:使用同一个对象(锁)才能实现, 6 * 静态方法的同步则只能使用类的字节码也就是ClassName.class来做锁 7 * @author yzl 8 * 9 */ 10 public class ThreadPart_2 { 11 public static void main(String[] args) { 12 noSyn(); 13 synWithOneObj(); 14 synWithOneStaticObj(); 15 } 16 17 /** 18 * 未线程同步的 19 */ 20 private static void noSyn(){ 21 final Work work = new Work(); 22 23 Thread thread = new Thread(new Runnable() { 24 @Override 25 public void run() { 26 while(true){ 27 work.noSynwrite("wangwu"); 28 } 29 } 30 }); 31 thread.start(); 32 33 Thread thread1 = new Thread(new Runnable() { 34 @Override 35 public void run() { 36 while(true){ 37 work.noSynwrite("zhangsan"); 38 } 39 } 40 }); 41 thread1.start(); 42 } 43 44 /** 45 * 使用同一个实例对象做为锁的 46 */ 47 private static void synWithOneObj(){ 48 final Work work = new Work(); 49 50 Thread thread = new Thread(new Runnable() { 51 @Override 52 public void run() { 53 while(true){ 54 work.write1("wangwu"); 55 } 56 } 57 }); 58 thread.start(); 59 60 Thread thread1 = new Thread(new Runnable() { 61 @Override 62 public void run() { 63 while(true){ 64 work.write2("zhangsan"); 65 } 66 } 67 }); 68 thread1.start(); 69 } 70 71 /** 72 * 使用同一个类的字节码做为锁的 73 */ 74 private static void synWithOneStaticObj(){ 75 Thread thread = new Thread(new Runnable() { 76 @Override 77 public void run() { 78 while(true){ 79 new Work().noSynwrite("wangwu"); 80 } 81 } 82 }); 83 thread.start(); 84 85 Thread thread1 = new Thread(new Runnable() { 86 @Override 87 public void run() { 88 while(true){ 89 Work.write3("zhangsan"); 90 } 91 } 92 }); 93 thread1.start(); 94 } 95 }
将上面ThreadPart_2的第12、13、14行代码分别依次执行,
第12行代码将出现如下类似结果:
//运行结果部分示例 zhangsan zhwu wangwu wangangsan zhangsawangwu
第13和14行将是正常的打印各自的名字