线程同步主要是为了防止多线程情况下,资源访问冲突。
举个栗子,卖票,还有 2 张票,A B 两个线程同时操作,A 线程把剩余的2张票都卖了,此时 B 线程已经执行完判断是否有票的逻辑,B 也卖了 2 张票。这显然是不对的。
多线程情况下,在对数据操作时要确保线程安全。
于是有了线程同步机制,用来解决资源共享问题。
线程同步机制 就是在给定范围内给资源加上一把锁,只允许一个线程访问资源。
1.线程不安全
以卖票(奶茶)为例,总数固定,每次减1 ,3个线程同时操作,
public class TestSynchronized {
public static void main(String[] args) {
BuyRunnable runnable = new BuyRunnable();
Thread thread1 = new Thread(runnable, "thread1");
Thread thread2 = new Thread(runnable, "thread2");
Thread thread3 = new Thread(runnable, "thread3");
thread1.start();
thread2.start();
thread3.start();
}
}
class BuyRunnable implements Runnable{
private int milkTeeSum = 10;
@Override
public void run() {
while (true) {
if (milkTeeSum > 0) {
try {
Thread.sleep(1000);//延时模拟卖奶茶
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("milkTee remain " + --milkTeeSum);
}
}
}
}
运行结果
milkTee remain 9
milkTee remain 8
milkTee remain 7
milkTee remain 6
milkTee remain 5
milkTee remain 4
milkTee remain 3
milkTee remain 2
milkTee remain 1
milkTee remain 0
milkTee remain -1
milkTee remain -2
出现负数,这是不对的。
2.线程同步
使用
synchronized
关键字来加锁,
public class TestSynchronized {
public static void main(String[] args) {
BuyRunnable runnable = new BuyRunnable();
Thread thread1 = new Thread(runnable, "thread1");
Thread thread2 = new Thread(runnable, "thread2");
Thread thread3 = new Thread(runnable, "thread3");
thread1.start();
thread2.start();
thread3.start();
}
}
class BuyRunnable implements Runnable{
private int milkTeeSum = 10;
@Override
public void run() {
while (true) {
synchronized (this){
if (milkTeeSum > 0) {
try {
Thread.sleep(1000);//延时模拟卖奶茶
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("milkTee remain " + --milkTeeSum);
}
}
}
}
}
运行结果,符合要求。
milkTee remain 9
milkTee remain 8
milkTee remain 7
milkTee remain 6
milkTee remain 5
milkTee remain 4
milkTee remain 3
milkTee remain 2
milkTee remain 1
milkTee remain 0
这是 同步块 。
还可以 同步方法,
public class TestSynchronized {
public static void main(String[] args) {
BuyRunnable runnable = new BuyRunnable();
Thread thread1 = new Thread(runnable, "thread1");
Thread thread2 = new Thread(runnable, "thread2");
Thread thread3 = new Thread(runnable, "thread3");
thread1.start();
thread2.start();
thread3.start();
}
}
class BuyRunnable implements Runnable{
private int milkTeeSum = 10;
@Override
public void run() {
while (true) {
soldMilkTee();
}
}
private synchronized void soldMilkTee(){
if (milkTeeSum > 0) {
try{
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("milkTee remain " + --milkTeeSum);
}
}
}
本例效果,和同步块是一样的。