本文共 3304 字,大约阅读时间需要 11 分钟。
同步的关键是多个线程对象竞争同一个共享对象,使无序的多个线程有序地排队。
Example 1:
public class Thread06_sync { public static void main(String[] args) {// new Thread06_sync().test01(); new Thread06_sync().new Test02(new Object()).test02(); } // 同步失败,原因:不是同步同一个对象 public void test01() { for (int i = 1; i <= 3; ++i) { new Thread(new Runnable() { public synchronized void run() { for (int i = 1; i <= 5; ++i) { System.out.println("id:" + Thread.currentThread().getId() + ",i:" + i); } } }).start(); } } // 同步成功,原因:同步同一个对象 public class Test02 { private Object thisThread; public Test02(Object thisThread) { this.thisThread = thisThread; } public void test02() { for (int i = 1; i <= 3; ++i) { new Thread(new Runnable() { public void run() { synchronized (thisThread) { for (int i = 1; i <= 5; ++i) { System.out.println("id:" + Thread.currentThread().getId() + ",i:" + i); } } } }).start(); } } }}
第一个例子,如果不同的synchronized object, 则不能正确lock住代码片段。
Example 2:
public class Thread04_static { // volatile 只是可见一致性,非原子性(也就是无写锁),仍然有机会有重复uniqueNumber的输出 public volatile static long uniqueNumber = 0; static int threadNumber = 5; static AtomicInteger testNum = new AtomicInteger(0); static List第二个例子,static 和 非static的不同,也会导致lock的失败。resultList = new ArrayList<>(300); private final static ReentrantLock lock = new ReentrantLock(); public static void main(String[] args) { testThread01(); } // CountDownLatch public static void testThread01() { try { CountDownLatch doneSignal = new CountDownLatch(50); for (int i = 0; i < threadNumber; i++) { Thread thread = new Thread(new Thread04_static().new TestThread01(doneSignal)); thread.setName("t_" + i); thread.start(); } // 由于thread的无序性,不加await的话, 有可能运行下面语句时thread还没运行,resultList有可能是空值 doneSignal.await(); int i = 1; for (Long result : resultList) { System.out.println("result_" + i + ":" + result); ++i; } } catch (Exception e) { e.printStackTrace(); } } // 静态类及非静态同步、锁测试 public class TestThread01 implements Runnable { private CountDownLatch doneSignal; public TestThread01(CountDownLatch doneSignal) { this.doneSignal = doneSignal; } public void run() { try { // 第一个同步block/ReentrantLock:这里的同步无预期效果(即有重复的uniqueNumber出现),因为getUniqueNum是类静态方法// synchronized (this) {// lock.lock(); for (int i = 0; i < 10; i++) {// System.out.println(testNum.addAndGet(1)); // 有重复的testNum出现, 原因:testNum是原子的,但下面的语句不原子// System.out.println("Thread:" + Thread.currentThread().getName() + ", testNum:" + testNum + ", i:" + i); resultList.add(getUniqueNum(2)); doneSignal.countDown(); } // 空行不一定每十条记录输出一次,因为它不在下面的静态同步block System.out.println(""); Thread.sleep(1000);// } } catch (Exception e) { e.printStackTrace(); } finally {// lock.unlock(); } } } public static Long getUniqueNum(int len) { // 第二个同步block/ReentrantLock:静态类同步block/lock,实现无重复uniqueNumber输出// synchronized (TestThread01.class) { try{ lock.lock(); if (len < 1) { return null; } if (uniqueNumber < (Math.pow(10, len) - 1)) { uniqueNumber++; } System.out.println("Thread:" + Thread.currentThread().getName() + ", uniqueNumber:" + uniqueNumber); return uniqueNumber; } finally { lock.unlock(); }// } }}
转载地址:http://pwili.baihongyu.com/