内容简介:当多个线程同时共享,同一个全局变量或静态变量,做写的操作时,可能会发生数据冲突问题,也就是线程安全问题。但是做读操作是不会发生数据冲突问题结果:火车票会重复出售使用多线程之间同步synchronized或使用锁(lock)
当多个线程同时共享,同一个全局变量或静态变量,做写的操作时,可能会发生数据冲突问题,也就是线程安全问题。但是做读操作是不会发生数据冲突问题
模拟线程安全问题
public class SafeThread implements Runnable {
private int ticketCount = 50;
@Override
public void run() {
while (ticketCount > 0) {
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + ",出售第" + (50 - ticketCount + 1) + "张票");
ticketCount--;
}
}
}
@RequestMapping("test-safe")
public void testSafe() {
SafeThread safeThread = new SafeThread();
Thread t1 = new Thread(safeThread, "thread-1");
Thread t2 = new Thread(safeThread, "thread-2");
t1.start();
t2.start();
}
结果:火车票会重复出售
解决办法
使用多线程之间同步synchronized或使用锁(lock)
1.同步代码块
public class SafeThread implements Runnable {
private int ticketCount = 50;
@Override
public void run() {
while (ticketCount > 0) {
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (this) {
System.out.println(Thread.currentThread().getName() + ",出售第" + (50 - ticketCount + 1) + "张票");
ticketCount--;
}
}
}
}
2.同步方法
public class SafeThread implements Runnable {
private int ticketCount = 50;
@Override
public void run() {
while (ticketCount > 0) {
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
// synchronized (this) {
// System.out.println(Thread.currentThread().getName() + ",出售第" + (50 - ticketCount + 1) + "张票");
// ticketCount--;
// }
sale();
}
}
private synchronized void sale() {
System.out.println(Thread.currentThread().getName() + ",出售第" + (50 - ticketCount + 1) + "张票");
ticketCount--;
}
}
注意:同步函数使用this锁
3.静态同步函数
方法上加上static关键字,使用synchronized 关键字修饰或者使用类.class文件。
静态的同步函数使用的锁是该函数所属字节码文件对象
可以用 getClass方法获取,也可以用当前类名.class 表示
public class SafeThread implements Runnable {
private int ticketCount = 50;
@Override
public void run() {
while (ticketCount > 0) {
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
// synchronized (this) {
// System.out.println(Thread.currentThread().getName() + ",出售第" + (50 - ticketCount + 1) + "张票");
// ticketCount--;
// }
// sale();
sale2();
}
}
private synchronized void sale() {
System.out.println(Thread.currentThread().getName() + ",出售第" + (50 - ticketCount + 1) + "张票");
ticketCount--;
}
private void sale2() {
synchronized (SafeThread.class) {
System.out.println(Thread.currentThread().getName() + ",出售第" + (50 - ticketCount + 1) + "张票");
ticketCount--;
}
}
}
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- Callable,阻塞队列,线程池问题
- 虚拟机线程问题分析(一):服务调优或问题排查执行方案
- Android子线程和更新UI问题
- 【Android多线程】哲学家就餐问题
- Hystrix系列之ThreadLocal跨线程传递问题
- 多线程Django程序耗尽数据库连接的问题
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。