1.什么线程安全问题?
1.1 就是当多个线程共享同一个全局变量,同时对这个变量做写的时间,可能会受到其他线程的干扰,导致数据有误。
class ThreadDemos implements Runnable {
private int movie = 8;
@Override
public void run() {
while (movie > 0) {
try {
Thread.sleep(10);
} catch (Exception e) {
// TODO: handle exception
}
sell();
}
}
public void sell() {
if (movie > 0) {
System.out.println(Thread.currentThread().getName() + ",出售第" + (8 - movie + 1) + "票");
movie--;
}
}
}
public class ThreadDemo {
public static void main(String[] args) {
ThreadDemos threadDemos = new ThreadDemos();
Thread t1 = new Thread(threadDemos, "美团买票");
Thread t2 = new Thread(threadDemos, "门店买票");
t1.start();
t2.start();
}
}
运行结果:
由此我们可以发现2个窗口会出现同一张票,就出现了线程安全问题,如果2个不同的人买了同一张票,这个时间检票员是该让哪个人进去看电影那?
2.怎么样解决线程安全问题?
2.1 使用synchronized 同步代码块 代码如下:
class ThreadDemos implements Runnable {
private int movie = 8;
private Object object = new Object();
@Override
public void run() {
while (movie > 0) {
try {
Thread.sleep(10);
} catch (Exception e) {
// TODO: handle exception
}
sell();
}
}
public void sell() {
synchronized (object) {
if (movie > 0) {
System.out.println(Thread.currentThread().getName() + ",出售第" + (8 - movie + 1) + "票");
movie--;
}
}
}
}
public class ThreadDemo {
public static void main(String[] args) {
ThreadDemos threadDemos = new ThreadDemos();
Thread t1 = new Thread(threadDemos, "美团买票");
Thread t2 = new Thread(threadDemos, "门店买票");
t1.start();
t2.start();
}
}
代码运行结果:
使用 synchronized 同步代码块 就不会出现2个窗口会出现同一张票的安全性问题
使用synchronized 的 条件:1.必须要有2个线程以上的,需要同步 2.多个线程想要同步,必须要使用同一把锁 3.保证只有一个线程运行执行
使用synchronized 同步代码块 的原理:有一个线程已经拿到锁了,其他线程已经有cpu执行的,那么这个线程会等待拿到锁的那个线程执行完毕释放锁
使用synchronized 的缺点:效率低,因为线程会抢锁
2.2使用 同步函数解决线程安全:
class ThreadDemos implements Runnable {
private int movie = 8;
@Override
public void run() {
while (movie > 0) {
try {
Thread.sleep(10);
} catch (Exception e) {
// TODO: handle exception
}
sell();
}
}
public synchronized void sell() {
if (movie > 0) {
System.out.println(Thread.currentThread().getName() + ",出售第" + (8 - movie + 1) + "票");
movie--;
}
}
}
public class ThreadDemo05 {
public static void main(String[] args) {
ThreadDemos threadDemos = new ThreadDemos();
Thread t1 = new Thread(threadDemos, "美团买票");
Thread t2 = new Thread(threadDemos, "门店买票");
t1.start();
t2.start();
}
}
代码运行结果:
使用同步函数 在需要同步的方法上面加上 synchronized 关键字,同步函数使用的是 this 锁
2.3使用静态同步函数
class ThreadDemos implements Runnable {
private static int movie = 8;
@Override
public void run() {
while (movie > 0) {
try {
Thread.sleep(10);
} catch (Exception e) {
// TODO: handle exception
}
sell();
}
}
public static synchronized void sell() {
if (movie > 0) {
System.out.println(Thread.currentThread().getName() + ",出售第" + (8 - movie + 1) + "票");
movie--;
}
}
}
public class ThreadDemo05 {
public static void main(String[] args) {
ThreadDemos threadDemos = new ThreadDemos();
Thread t1 = new Thread(threadDemos, "美团买票");
Thread t2 = new Thread(threadDemos, "门店买票");
t1.start();
t2.start();
}
}
运行结果:
静态同步函数使用的是 当前字节码文件