Synchronized介绍
在Java中,"synchronized"是一个关键字,用于实现线程同步。
背景
在多线程编程中,当多个线程同时访问共享资源时,可能会出现竞态条件(Race Condition)和数据不一致的问题。为了解决这个问题,Java提供了内置的同步机制,即"synchronized"关键字。
使用"synchronized"关键字可以对代码块或方法进行同步,保证在同一时间只有一个线程可以执行同步代码块或方法。当一个线程访问同步代码块或方法时,它会获得锁(也称为监视器锁),其他线程将被阻塞,直到获得锁的线程释放锁。
使用方式
1. 同步代码块
2. 同步方法
3. 静态同步方法
同步代码块的方式
需求
需求: 某电影院目前正在上映国产大片,共有10@张票,而它有3个窗口卖票,请设计一个程序模拟该电影院卖票
代码实现
线程类
public class MyThread extends Thread{
// static 表示这个类所有对象共享该属性
static int ticket = 0;
@Override
public void run() {
while (true){
synchronized (MyThread.class){
if (ticket < 20){
try {
Thread.sleep(10);
ticket++;
System.out.println(getName()+" 正在卖票 "+ticket);
} catch (InterruptedException e) {
e.printStackTrace();
}
}else{
System.out.println(getName()+" 票卖完了....");
break;
}
}
}
}
}
测试类
public class ThreadDemo {
public static void main(String[] args) {
// 创建线程对象
MyThread t1 = new MyThread();
MyThread t2 = new MyThread();
MyThread t3 = new MyThread();
// 起名
t1.setName("窗口1");
t2.setName("窗口2");
t3.setName("窗口3");
// 开启
t1.start();
t2.start();
t3.start();
}
}
实现细节
①同步代码块不能写在循环的外面
②锁对象:可以是任意一个对象,但一定要是唯一的
说明
同步代码块不能写在循环的外面: 因为如果写在循环外面,一旦有一个线程对象获取到了锁,该对象就会一直执行,直至循环条件结束。 这样就会导致其他线程对象就算抢夺到了CPU 的执行权,也没能得到锁,不能参与执行,也就没有意义了
锁对象:可以是任意一个对象,但一定要是唯一的 因此这里不能用this,因为this代表当前对象;在测试类中创建对象时,有三个线程类对象,即三个对象都是当前对象,导致对象不唯一,达不到锁的效果