什么是线程不安全
以卖票为例
package demo;
public class Demo1 {
public static void main(String[] args) {
//线程不安全
Runnable run = new Ticket();
new Thread(run).start();
new Thread(run).start();
new Thread(run).start();
}
static class Ticket implements Runnable{
//票数
private int count = 10;
@Override
public void run() {
while(count>0){
//卖票
System.out.println("正在准备卖票");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
count--;
System.out.println("出票成功,余票:"+count);
}
}
}
}
运行结果
解决方案一:同步代码块
格式:synchronized(锁对象){
同步代码块
}
package demo;
public class Demo2 {
/**
* 同步代码块
* @param args
*/
public static void main(String[] args) {
Object o = new Object();
Runnable run = new Demo2.Ticket();
new Thread(run).start();
new Thread(run).start();
new Thread(run).start();
}
static class Ticket implements Runnable{
//票数
private int count = 10;
private Object o = new Object();
@Override
public void run() {
while(true){
synchronized (o){
if(count>0){
System.out.println("正在准备卖票");
try{
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
count--;
System.out.println(Thread.currentThread().getName()+"出票成功,余票:"+count);
}else{
break;
}
}
}
}
}
}
解决方案二:同步方法
创建一个方法,添加synchronized修饰符
package demo;
public class Demo3 {
/**
* 同步方法
* @param args
*/
public static void main(String[] args) {
Runnable run = new Ticket();
new Thread(run).start();
new Thread(run).start();
new Thread(run).start();
}
static class Ticket implements Runnable{
private int count = 10;
@Override
public void run() {
while(true){
boolean flag = sale();
if(!flag){
break;
}
}
}
public synchronized boolean sale(){
if(count>0){
System.out.println("正在准备卖票");
try{
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
count--;
System.out.println(Thread.currentThread().getName()+"出票成功,余票"+count);
return true;
}
return false;
}
}
}
解决方案三:显式锁 Lock子类 ReentrantLock();
package demo;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class Demo4 {
public static void main(String[] args) {
//线程不安全
Runnable run = new Ticket();
new Thread(run).start();
new Thread(run).start();
new Thread(run).start();
}
static class Ticket implements Runnable{
//票数
private int count = 10;
Lock l = new ReentrantLock();
@Override
public void run() {
while(true){
l.lock();
if(count>0){
System.out.println("正在准备卖票");
try{
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
count--;
System.out.println(Thread.currentThread().getName()+"出票成功,余票:"+count);
}else{
break;
}
l.unlock();
}
}
}
}