java 多线程安全--- synchronized 关键字

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();
}

}
运行结果:

静态同步函数使用的是 当前字节码文件

猜你喜欢

转载自www.cnblogs.com/cwj1102/p/13354381.html