线程类中的实例变量针对其他线程可以有共享和不共享之分。下面通过两个简单的例子来说明!
1、不共享数据的情况
public class MyThread extends Thread{
private int count = 5;
public MyThread(String name){
super();
this.setName(name);
}
@Override
public void run(){
super.run();
while (count > 0)
{
count--;
System.out.println("由 " + MyThread.currentThread().getName() + " 计算,count=" + count);
}
}
public static void main(String[] args){
MyThread a = new MyThread("A");
MyThread b = new MyThread("B");
MyThread c = new MyThread("C");
a.start();
b.start();
c.start();
}
}
运行结果:
可以看出每个线程都有一个属于自己的实例变量count,它们之间互不影响。我们再来看看另一种情况。
2、共享数据的情况
public class SharedVariableThread extends Thread{
private int count = 5;
@Override
public void run(){
super.run();
count--;
System.out.println("由 " + SharedVariableThread.currentThread().getName() + " 计算,count=" + count);
}
public static void main(String[] args){
SharedVariableThread mythread = new SharedVariableThread();
// 下列线程都是通过mythread对象创建的
Thread a = new Thread(mythread, "A");
Thread b = new Thread(mythread, "B");
Thread c = new Thread(mythread, "C");
Thread d = new Thread(mythread, "D");
Thread e = new Thread(mythread, "E");
a.start();
b.start();
c.start();
d.start();
e.start();
}
}
运行结果:
可以看出这里已经出现了错误,我们想要的是依次递减的结果。为什么呢??
因为在大多数jvm中,count–的操作分为如下下三步:
1、取得原有count值
2、计算i -1
3、对i进行赋值
所以多个线程同时访问时出现问题就是难以避免的了。
那么有没有什么解决办法呢?
答案是:当然有,而且很简单。给大家提供两种解决办法:一种是利用 synchronized 关键字(保证任意时刻只能有一个线程执行该方法),一种是利用 AtomicInteger 类(JUC 中的 Atomic 原子类)。大家如果之前没有接触 Java 多线程的话,可能对这两个概念不太熟悉,不过不要担心我后面会一一向你介绍到!这里不能用 volatile 关键字,因为 volatile 关键字不能保证复合操作的原子性。