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);是一个本地方法。