Thread - synchronized

来源:互联网 发布:梦幻小号注册软件 编辑:程序博客网 时间:2024/05/22 03:47

同步的关键是多个线程对象竞争同一个共享对象,使无序的多个线程有序地排队。

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<Long> resultList = new ArrayList<>(300);private final static ReentrantLock lock = new ReentrantLock();public static void main(String[] args) {testThread01();}// CountDownLatchpublic 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();}// 空行不一定每十条记录输出一次,因为它不在下面的静态同步blockSystem.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();}//}}}

第二个例子,static 和 非static的不同,也会导致lock的失败。

0 0
原创粉丝点击