本文共 1793 字,大约阅读时间需要 5 分钟。
在并发编程中,线程安全问题是很常见的,主要形式包括共享数据和多线程同时操作共享数据。为了应对这些挑战,Java提供了synchronized
关键字,它在以下方面发挥着重要作用:
volatile
关键字。例如,在下面的代码中,如果不使用synchronized
,可能会导致火车票重复出售的问题:
public class TestDemo implements Runnable { private volatile int count = 100; @Override public void run() { while (count > 0) { Thread.sleep(50); sale(); } } public void sale() { if (count > 0) { System.out.println(Thread.currentThread().getName() + "出售 :" + (100 - count + 1)); count--; } }}
synchronized
的作用机制可以分为以下几个方面:
在 Java 中,synchronized
锁可以应用在三个不同的方式中:
普通同步方法(实例方法):
synchronized
修饰方法时,进入方法前需要获取当前实例对象的锁。public synchronized void sale() { if (count > 0) { System.out.println("窗口一出售 :" + (100 - count)); count--; }}
静态同步方法:
synchronized
修饰静态方法时,进入方法前需要获取当前类对象的锁。public static synchronized void sale() { if (count > 0) { System.out.println("窗口一出售 :" + (100 - count)); count--; }}
同步代码块:
synchronized
时,进入方法前需要获取括号内对象的锁。private Object object = new Object();public void sale() { synchronized (object) { if (count > 0) { System.out.println("窗口一出售 :" + (100 - count)); count--; } }}
在 JDK 1.6 之前,synchronized
实现的加锁和解锁操作非常重量级,会导致线程上下文切换和额外性能开销。新版本中,synchronized
实现了偏向锁机制,结合轻量级锁和冲突检测机制(cas
),从而大幅降低锁的开销。
synchronized
是支持可重入锁设计的。这意味着一个线程在持有一个对象锁的情况下,其它线程同样可以请求该对象锁。但必须注意,如果请求的是同一个对象锁,一定会等待;如果请求的是不同的对象锁,则会立即获取。这种方式避免了死锁,而不会导致资源浪费。
转载地址:http://bwwaz.baihongyu.com/