线程不安全
原因:
- 多个线程去争抢一个数据,导致某个阶段会出现一个数据被多个线程更改,从而出现错误。
解决方法:
- synchronized(锁对象){要锁住的代码块}
注意,要看同一把锁,不能每个线程都生成自己的锁对象,要多个线程拥有一个所对象。
- synchronized 要锁的方法
格式大体上如图所示:
- 显示锁 Lock 子类 ReentrantLock
公平锁:先来先到,排队
非公平锁:谁先抢到就是谁的
三种方法的例子:
- synchronized(锁对象){要锁住的代码块}
/**
* 线程同步:synchronized
* @param args
*/
public static void main(String[] args) {
//线程不安全
//解决方案一:同步代码块
//格式:synchronized(锁对象){这里面是同步的代码块}
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;
private Object o =new Object(); //这里的o就是锁
@Override
public void run() {
// Object o =new Object();
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
* @param args
*/
public static void main(String[] args) {
//线程不安全
//解决方案二:同步方法
//格式:synchronized(锁对象){这里面是同步的代码块}
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;
}
}
- 显示锁
/**
* 线程同步:synchronized
* @param args
*/
public static void main(String[] args) {
//线程不安全
//解决方案三:显示锁 Lock 子类 ReentrantLock
//
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;
//显示锁 l fail参数为true就是公平锁,false就是非公平锁
private 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();
}
}
}