目录
一、单线程获取值案例(没有产生线程安全性问题)
- 一、单线程获取值案例(没有产生线程安全性问题)
- 二·、多线程获取值案例(产生线程安全性问题)
- 三、从字节码角度看线程安全性问题的示例
- 四、如何解决多线程安全性问题的示例
- 五、如何产生线程安全性问题
1、代码
package com.xz.thread.t3;
/**
* @description: 单线程情况下输出没有问题
* @author: xz
*/
public class Sequeue {
private int value;
public int getNext(){
return value++;
}
public static void main(String[] args) {
Sequeue sequeue = new Sequeue();
while(true){
System.out.println(sequeue.getNext());
}
}
}
2、输出结果如下: 3、结论
- 单线程运行,输出结果依次递增,不会出现重复数据。
1、代码
package com.xz.thread.t3;
/**
* @description: 单线程情况下输出没有问题
* @author: xz
*/
public class Sequeue {
private int value;
public int getNext(){
return value++;
}
public static void main(String[] args) {
Sequeue sequeue = new Sequeue();
new Thread(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+" "+sequeue.getNext());
try {
Thread.sleep(100);
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
while(true){
System.out.println(Thread.currentThread().getName()+" "+sequeue.getNext());
try {
Thread.sleep(100);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
while(true){
System.out.println(Thread.currentThread().getName()+" "+sequeue.getNext());
try {
Thread.sleep(100);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}).start();
}
}
2、输出结果如下: 3、结论
- 多线程运行,输出结果依次递增,但是会出现重复数据。因此产生安全问题。
1、找到第三步编译的Sequeue的字节码文件,如下图: 2、dos命令行窗口进入t3文件夹,并执行javap -verbose Sequeue.class 命令,如下图:
3、找到 getNext()方法,如下图:
4、结论:
- 由上图可知,getNext方法并不是一步操作即完成,而是分成了多个步骤,所以多线程访问会出现相同数值问题。
1、在getNext方法上加上synchronized关键字,代码如下:
package com.xz.thread.t3;
/**
* @description: 单线程情况下输出没有问题
* @author: xz
*/
public class Sequeue {
private int value;
public synchronized int getNext(){
return value++;
}
public static void main(String[] args) {
Sequeue sequeue = new Sequeue();
new Thread(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+" "+sequeue.getNext());
try {
Thread.sleep(100);
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
while(true){
System.out.println(Thread.currentThread().getName()+" "+sequeue.getNext());
try {
Thread.sleep(100);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
while(true){
System.out.println(Thread.currentThread().getName()+" "+sequeue.getNext());
try {
Thread.sleep(100);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}).start();
}
}
2、输出结果如下图:
3、结论
- 由上图输出结果可知,没有重复值的情况,解决了多线程安全性问题。
- 多线程环境下
- 多个线程共享一个资源
- 对资源进行非原子性操作