目录
synchronized 是 Java 中用于实现线程同步的关键字。它可以在方法级别或代码块级别使用,以确保同一时刻只有一个线程可以访问被同步的代码段。synchronized 通过内部锁机制来实现线程间的互斥访问
synchronized 关键字可以在方法级和代码块级使用:
①可以将 synchronized 用在方法级别上,这种情况下锁定的对象是当前对象(this)
public class MyClass {
public synchronized void myMethod() {
// synchronized 代码
}
}
②也可以将 synchronized 关键字用在代码块级别上,这种情况下锁定的对象可以是当前对象(this),也可以是任意一个对象
public class MyClass {
private final Object lock = new Object(); // 定义一个对象作为锁
public void myMethod() {
synchronized (lock) {
// synchronized 代码
}
}
}
🌰:多线程访问以下这段代码时,count结果会是多少呢?
public class SynchronizedTest implements Runnable{
public static int count = 0;
@Override
public void run() {
addCount();
}
public void addCount(){
int i = 0;
while (i++ < 1000) {
count++;
}
}
public static void main(String[] args) throws Exception{
SynchronizedTest obj = new SynchronizedTest();
Thread t1 = new Thread(obj);
Thread t2 = new Thread(obj);
t1.start();
t2.start();
t1.join(); // 等待 t1 线程执行完毕
t2.join(); // 等待 t2 线程执行完毕
System.out.println(count); // 打印 count 的值
}
}
逻辑很简单, 最终的count值一定是<2000,由于t1线程获取count的值为0,然后执行了+1操作,但还未同步至主内存,此时,t2获取主内存中count=0,然后也执行了+1操作,那最终的结果依然是count=1
为了保证count的值=2000,就需要用到synchronized关键字
1、synchronized适用场景
- 多线程环境下需要保证代码块或方法的原子性:
当需要确保一段代码在多线程环境中只被一个线程执行时,可以使用 synchronized。
- 保证多个变量之间的一致性:
当需要保证多个变量之间的操作是一致的时候,可以使用 synchronized 来确保这些操作作为一个整体被执行。
- 防止死锁:
虽然 synchronized 可能会导致死锁,但也可以通过合理的锁顺序和锁粒度设计来预防死锁。
- 保证可见性和有序性:
synchronized 关键字还可以保证可见性和有序性,确保线程间的数据同步
上面都是一些很空泛的概念,有木有,因此还是需要结合🌰来深入了解synchronized
掌声欢迎👏👏👏,🌰登场!
在上文中Java并发—CAS的原理及应用场景-优快云博客讲了利用CAS来实现抢票功能,没看过上文,也没关系,有兴趣可以看看,哈哈哈……
CAS操作多个变量时,会比较复杂,虽然保证多变量的一致性更新,但可能需要多次 CAS 操作和自旋重试,可能会消耗更多的 CPU 资源,那如果使用synchronized关键字实现上述功能呢
还是以之前的案例🌰:假设线程A和线程B,都在尝试购买不同活动的门票
public class Ticket {
private int remainingTickets = 100; // 剩余票数
private int eventId = 1; // 活动 ID
public synchronized void buyTicket(int ticketsToBuy, int eventId) {
if (remainingTickets >= ticketsToBuy) {
this.eventId = eventId; // 更新活动 ID
System.out.println(Thread.currentThread().getName() + " 成功购买 " + ticketsToBuy + " 张票");
re