Java多线程之synchronized
- - CSDN博客推荐文章这里通过三个测试类阐述了synchronized应用的不同场景. 首先是最基本的synchronized Method的使用. * @see 概述:Java中的每个对象都有一个锁(lock)或者叫做监视器(monitor) . * @see 说明:当synchronized关键字修饰一个方法时,则该方法为同步方法 .
public synchronized static void function04() {//类锁 try { Test05.class.wait();//本类的wait池 } catch (InterruptedException e) { e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. } } public void function02() { synchronized (lock) {//lock锁 try { lock.wait();//同样为lock锁的wait池 } catch (InterruptedException e) { e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. } } }
|
可见性 |
互斥性 |
synchronized |
块可见 |
块互斥 |
volatile |
变量可见 |
变量互斥(无意义) |
无锁编程(Unsafe) |
变量可见 |
不保证 |
/** * Created with IntelliJ IDEA. * User: yangzl2008 * Date: 14-10-25 * Time: 下午8:31 * To change this template use File | Settings | File Templates. */ public class TeshSynchronized { Object lock = new Object(); public synchronized void function01() { } public void function02() { synchronized (lock) { } } public void function03() { synchronized (this) { } } public synchronized static void function04() { } public void function05() { synchronized (TeshSynchronized.class) { } } }
|
同一对象 |
不同对象但同一类 |
对象锁 |
多线程互斥 |
多线程不互斥 |
类锁 |
多线程互斥 |
多线程互斥 |
/** * Created with IntelliJ IDEA. * User: yangzl2008 * Date: 14-10-26 * Time: 下午10:09 * To change this template use File | Settings | File Templates. */ public class TestVolatile { private volatile int a1; //多线程可见 private int a2; //多线程有问题 private int a3; public int getA1() { return a1; } public void setA1(int a1) { this.a1 = a1; } public int getA2() { return a2; } public void setA2(int a2) { this.a2 = a2; } public int getA3() { return a3; } public synchronized void setA3(int a3) { this.a3 = a3; } }
/** * Created with IntelliJ IDEA. * User: yangzl2008 * Date: 14-10-26 * Time: 下午10:21 * To change this template use File | Settings | File Templates. */ public class TestVolatile2 { volatile int count; Map<String, String> map = new ConcurrentHashMap<String, String>(); public void addContent(String key, String value) { if (count < 100) { map.put(key, value); count++; } } @Test public void testAddContent() throws Exception { ExecutorService executorService = Executors.newFixedThreadPool(10); for (int i = 0; i < 10; i++) { executorService.execute(new AddContentTask()); } // 关闭启动线程 executorService.shutdown(); // 等待子线程结束,再继续执行下面的代码 executorService.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS); System.out.println(map.size()); } private final class AddContentTask implements Runnable { @Override public void run() { //每个线程放11次 for (int i = 0; i <= 10; i++) { addContent(Thread.currentThread().getName() + " " + System.currentTimeMillis() + " " + i, "value"); } } } }以上判断count判断到达100后,就无法再向map当中放东西,但实际上,map当中的数量绝大多数情况下是大于100的。因此,volatile只能保证变量的可见性,而并不能保证块的互斥性,在某些情况下,其是无法代替synchronized的。
static { try { valueOffset = unsafe.objectFieldOffset (AtomicInteger.class.getDeclaredField("value")); } catch (Exception ex) { throw new Error(ex); } } private volatile int value;在我们调用getAndIncrement时,其代码如下:
public final int getAndIncrement() { for (;;) { int current = get(); int next = current + 1; if (compareAndSet(current, next)) return current; } }compareAndSet的代码如下:
public final boolean compareAndSet(int expect, int update) { return unsafe.compareAndSwapInt(this, valueOffset, expect, update); }其中unsafe.compareAndSwapInt(this, valueOffset, expect, update);是一个本地方法。