什么是原子操作?
所谓原子操作,就是"不可中断的一个或一系列操作" , 在确认一个操作是原子的情况下,多线程环境里面,我们可以避免仅仅为保护这个操作在外围加上性能昂贵的锁,甚至借助于原子操作,我们可以实现互斥锁。 很多操作系统都为int类型提供了+-赋值的原子操作版本,比如 NT 提供了 InterlockedExchange 等API, Linux/UNIX也提供了atomic_set 等函数。
关于java中的原子性?
原子性可以应用于除long和double之外的所有基本类型之上的“简单操作”。对于读取和写入出long double之外的基本类型变量这样的操作,可以保证它们会被当作不可分(原子)的操作来操作。 因为JVM的版本和其它的问题,其它的很多操作就不好说了,比如说++操作在C++中是原子操作,但在Java中就不好说了。 另外,Java提供了AtomicInteger等原子类。再就是用原子性来控制并发比较麻烦,也容易出问题。
volatile原理是什么?
Java中volatile关键字原义是“不稳定、变化”的意思
使用volatile和不使用volatile的区别在于JVM内存主存和线程工作内存的同步之上。volatile保证变量在线程工作内存和主存之间一致。
其实是告诉处理器, 不要将我放入工作内存, 请直接在主存操作我.
以下一段有意思的代码:
package jdk.thread;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class TestMultiThread implements Runnable {
private static int i;
private static volatile Integer vi = 0;
private static AtomicInteger ai = new AtomicInteger();
private static Integer si = 0;
private static int ri;
private static AtomicInteger flag = new AtomicInteger();
private Lock lock = new ReentrantLock();
@Override
public void run() {
for (int k = 0; k < 200000; k++) {
i++;
vi++;
ai.incrementAndGet();
synchronized (si) {
si++;
}
lock.lock();
try {
ri++;
} finally {
lock.unlock();
}
}
flag.incrementAndGet();
}
public static void main(String[] args) throws InterruptedException {
TestMultiThread t1 = new TestMultiThread();
TestMultiThread t2 = new TestMultiThread();
ExecutorService exec1 = Executors.newCachedThreadPool();
ExecutorService exec2 = Executors.newCachedThreadPool();
exec1.execute(t1);
exec2.execute(t2);
while (true) {
if (flag.intValue() == 2) {
System.out.println("i >>>>>" + i);
System.out.println("volatile vi >>>>>" + vi);
System.out.println("AtomicInteger ai >>>>>" + ai);
System.out.println("synchronized si >>>>>" + si);
System.out.println("lock ri >>>>>" + ri);
exec1.shutdown();
exec2.shutdown();
break;
}
Thread.sleep(50);
}
}
}
运行结果如下:
i >>>>>395805
volatile vi >>>>>369741
AtomicInteger ai>>>>>400000
synchronized si>>>>>379400
lock ri>>>>>392087
volatile,因为java中++不是原子操作,所以值不正确。
synchronized 锁定的不是同一个对象,因为si对象一直在变,改成如下代码则正确:
synchronized (Integer.class) {
si++;
}
lock 锁定的不是同一个对象,加static关键字修饰,改成类变量则正确。
private static Lock lock = new ReentrantLock();
参考:http://blog.csdn.net/luohuacanyue/article/details/7796352