java中处理并发主要有两种方式:
1,synchronized关键字,这个大家应当都各种面试和笔试中经常遇到。
2,volatile修饰符的使用,相信这个修饰符大家平时在项目中使用的也不是很多。
说说volatile:
Volatile修饰的成员变量在每次被线程访问时,都强迫从共享内存重新读取该成员的值,而且,当成员变量值发生变化时,强迫将变化的值重新写入共享内存,这样两个不同的线程在访问同一个共享变量的值时,始终看到的是同一个值。有点类似CAS(compare-and-swap)。
i++或者++i都是多线程不安全的。想知道原因请参考如下地址:
http://blog.csdn.net/zrh_lawliet/article/details/53544303
如下面错误程序。
package src;
import java.util.ArrayList;
import java.util.List;
class Count { public int i=0; }
class CountRunnable implements Runnable{
Count count = null;
public CountRunnable(Count count) {
this.count = count;
}
public synchronized void add(){
for(int j=0;j<100;j++){
count.i++;
}
}
@Override
public void run() { add(); }
}
public class TestAtomic {
public static void main(String[] args) throws InterruptedException {
for(int testNum = 0;testNum<5;testNum++){
Count count = new Count();
List<Thread> trd = new ArrayList<Thread>();
for(int threadNum =0;threadNum<1000;threadNum++){
Thread t = new Thread(new CountRunnable(count));
trd.add(t);
t.start();
}
for(int i =0;i<1000;i++){
trd.get(i).join();
}
System.out.println(count.i);
}
}
}
运行结果
正确使用AtomicInteger的方式如下:
package src;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
class Count {
public AtomicInteger i=new AtomicInteger();
//public int i = 0;
}
class CountRunnable implements Runnable{
Count count = null;
public CountRunnable(Count count) {
this.count = count;
}
public synchronized void add(){
for(int j=0;j<100;j++){
count.i.getAndAdd(1);
//count.i++;
}
}
@Override
public void run() { add(); }
}
public class TestAtomic {
public static void main(String[] args) throws InterruptedException {
for(int testNum = 0;testNum<5;testNum++){
Count count = new Count();
List<Thread> trd = new ArrayList<Thread>();
for(int threadNum =0;threadNum<1000;threadNum++){
Thread t = new Thread(new CountRunnable(count));
trd.add(t);
t.start();
}
for(int i =0;i<1000;i++){
trd.get(i).join();
}
System.out.println(count.i);
}
}
}