当多个线程执行共享数据时,有可能出现线程安全问题;
线程安全问题:1、共享数据重复出现
2、出现的数据不在范围之内(比如售票是出现出售的票号为-1,0等等)
解决安全问题的方法有三种:
同步代码块:
格式:
synchronized(锁对象){
可能出现问题的代码(访问共享数据的代码)
}
注意:
1、锁对象可以是任意类对象
2、保证多个线程的锁对象是同一个
同步方法:
public synchronized 返回值类型 方法名称(参数){
}==public 返回值类型 方法名(){
synchronized (this){
可能出现问题的代码(访问共享数据的代码)
}
}
静态同步方法:
public static synchronized 返回值类型 方法名(){
}==public static 返回值类型 方法名(){
synchronized (class文件对象(Runnable.class))
}
lock锁:
package cn.itcase.day33.demo01.demo02.demo02;
public class DemoTiket {
public static void main(String[] args) {
// Runnablimpi1 r = new Runnablimpi1()
Runnablimpi2 r = new Runnablimpi2();
Thread t = new Thread(r);
Thread t2 = new Thread(r);
Thread t1 = new Thread(r);
t.start();
t1.start();
t2.start();
// Thread th = new Thread(r);
// Thread th1 = new Thread(r);
// Thread th2 = new Thread(r);
// th.start();
// th1.start();
// th2.start();
}
}
package cn.itcase.day33.demo01.demo02.demo02;
import java.util.concurrent.locks.ReentrantLock;
public class Runnablimpi2 implements Runnable{
private int ticket = 100;
ReentrantLock l = new ReentrantLock();
@Override
public void run() {
while(true){
l.lock();
if(ticket > 0){
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"正在买第"+ticket+"张票");
ticket--;
}
l.unlock();
}
}
}
package cn.itcase.day33.demo01.demo02.demo02;
public class Runnablimpi1 implements Runnable{
private int ticket = 100;
Object obj = new Object();
@Override
public void run() {
while(true){
synchronized(obj){
if(ticket > 0){
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"正在买第"+ticket+"张票");
ticket--;
}
}
}
}
}