1. 利用类对象进行同步
当两个线程访问同一个类对象时,发生竞争。同步加锁的是对象,而不是代码。
package thrds; public class FiveThread { public static void main(String args[]) { ThTst obj = new ThTst(); Thread t1 = new Thread(obj); // 两个线程用同一个对象,发生互斥(属于对象互斥) Thread t2 = new Thread(obj); t1.start(); t2.start(); } } class ThTst extends Thread { public void run() { tst(); } synchronized void tst() { System.out.println(Thread.currentThread().getId() + " in"); try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getId() + " out"); } } 输出结果: 15 in 15 out 14 in 14 out 如果将上述 main函数中改为: Thread t1 = new Thread(new ThTst()); // 使用两个对象,不会发生竞争 Thread t2 = new Thread(new ThTst()); 输出结果: 17 in 15 in 15 out 17 out
2. 使用类定义和 对象 进行同步(类.class)
即使两个线程分别访问不同的对象,也会发生竞争。加锁的是代码段。
因为一个类的类定义只有一个,因此,到加锁的地方,只能有一个线程进去执行。
注意:null不可用来作为同步对象。
package thrds; public class SixThread { public static void main(String args[]) { Thread t1 = new Thread(new ThTst2()); Thread t2 = new Thread(new ThTst2()); t1.start(); t2.start(); } } class ThTst2 extends Thread { private static Integer iObj = 9; public void run() { tst(); } synchronized void tst() { synchronized (ThTst2.class) { //这里可用任何类类型,如 String.class, Integer.class 或使用 其他对象如iObj 也是一样的 System.out.println(Thread.currentThread().getId() + " in"); try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getId() + " out"); } } } 输出结果: 14 in 14 out 16 in 16 out
3. 2中使用对象同步,用来同步的对象,可由参数传入。这样,可提供更多的灵活性,程序员可以控制哪几个线程竞争同一个对象。(在设计时可参考)
package thrds; import org.omg.CORBA.INV_OBJREF; public class SevenThread { public static void main(String args[]) { ThTst3 tObj1 = new ThTst3(); ThTst3 tObj2 = new ThTst3(); String lock = new String("lock"); tObj1.setLock(lock); tObj2.setLock(lock); Thread t1 = new Thread(tObj1); Thread t2 = new Thread(tObj2); t1.start(); t2.start(); } } class ThTst3 extends Thread { private String lock = null; @Override public void run() { tst(); } synchronized void tst() { synchronized (lock) { //同步对象由参数传入 System.out.println(Thread.currentThread().getId() + " in"); try { Thread.sleep(5000); } catch (InterruptedException e) { // TODO 自动生成的 catch 块 e.printStackTrace(); } System.out.println(Thread.currentThread().getId() + " out"); } } void setLock(String lock) { this.lock = lock; } } 输出结果: 15 in 15 out 16 in 16 out
synchronized关键字,多线程在同步时,需要看用来同步的对象(包括类定义)是不是唯一的。只有对象是唯一的时候,才会发生互斥。
时间: 2024-10-13 02:06:18