Java锁机制 synchronized 分析
发布时间:2021-12-05 17:43:48 所属栏目:教程 来源:互联网
导读:进行多线程编程的时候,需要考虑的是线程间的同步问题。对于共享的资源,需要进行互斥的访问。在Java中可以使用一些手段来达到线程同步的目的: 1. synchronized 2. ThreadLocal,线程本地变量 3. Java.util.concurrent.Lock Java中,线程会共享堆上的实例变
进行多线程编程的时候,需要考虑的是线程间的同步问题。对于共享的资源,需要进行互斥的访问。在Java中可以使用一些手段来达到线程同步的目的: 1. synchronized 2. ThreadLocal,线程本地变量 3. Java.util.concurrent.Lock Java中,线程会共享堆上的实例变量以及方法区的类变量,而栈上的数据是私有的,不必进行保护。synchronized方法或synchronized块将标记一块监视区域,线程在进入该区域时,需要获得对象锁或类锁,JVM将自动上锁。在这里,我们将探讨synchronized使用时的三种情况: 1. 在对象上使用synchronized 2. 在普通成员方法上使用synchronized 3. 在静态成员方法上使用synchronized 这三种线程同步的表现有何不同? 下面通过三段示例代码来演示这三种情况。这里模拟线程报数的场景。 情况一:在普通成员函数上使用synchronized public class MyThread extends Thread { public static void main(String[] args) throws Exception { for (int i = 1; i < 100; i++) { MyThread t = new MyThread(); t.setName("Thread="+i); t.start(); Thread.sleep(100); } } @Override public synchronized void run() { for (int i = 1; i < 10000; i++) { System.out.println(Thread.currentThread().getName() + ":" + i); } } } 对一个成员函数使用synchronized进行加锁,所获取的锁,是方法所在对象本身的对象锁。在这里,每个线程都以自身的对象作为对象锁,要对线程进行同步,要求锁对象必须唯一,所以这里多个线程间同步失败。 情况二:在对象上使用synchronized 这里在类中增加一个成员变量lock,在该变量上使用synchronized: public class MyThread1 extends Thread { private String lock; public MyThread1(String lock) { this.lock = lock; } public static void main(String[] args) throws Exception { String lock = new String("lock"); for (int i = 1; i < 100; i++) { Thread t = new MyThread1(lock); t.setName("Thread=" + i); t.start(); Thread.sleep(100); } } @Override public void run() { synchronized (lock) { for (int i = 1; i < 10000; i++) { System.out.println(Thread.currentThread().getName() + ":" + i); } } } } 100个线程在创建的时候,都传递了同一个lock对象(在main中创建的)去初始化线程类成员lock,因此,这100个线程都在同一个lock对象上进行synchronized同步。因此线程同步成功。 情况三:在静态成员函数上使用synchronized public class MyThread2 extends Thread { public static void main(String[] args) throws Exception { for (int i = 1; i < 10; i++) { Thread t = new MyThread2(); t.setName("Thread=" + i); t.start(); Thread.sleep(10); } } public static synchronized void func() { for (int i = 1; i < 100; i++) { System.out.println(Thread.currentThread().getName() + ":" + i); } } @Override public void run() { func(); } } 这种情况下,线程获得的锁是对象锁,而对象锁是唯一的,因此多个进程间也能同步成功。 ![]() (编辑:开发网_开封站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |