`

lock 锁class类对象和实例对象

阅读更多
java thread 线程中 的synchronized关键字 可以放到方法上,也可以修饰对象上
eg:
 private synchronized void testSyncMethod() {
   //当线程执行到此处时,它必须获得一个锁,此时锁定的对象是:调用此方法的对象a
 }

 private void testSyncMethod() {
  synchronized(this){
   //当线程执行到此处时,它必须获得一个锁,此时锁定的对象是:调用此方法的对象a
  } 
 }


synchronized 可以修饰任何对象(int 等基本类型不在范围内),当然也包括类对象A.class
eg:
class A {
private static synchronized void testSyncMethod() { 
  //此时当前线程获得的锁是:A.class
}

  private void testSyncMethod(){
   synchronized(A.class){
     //此时当前线程获得的锁是:A.class
    } 
  }

}


既然A.class ,对象a 不是同一对象,即synchronized  修饰普通方法和静态方法是锁定了不同的对象。
下面的代码示例:

package com.horizon.thread.classLock;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * synchronized 修饰 static方法 锁定的是 class对象
 * 即:synchronized (RunnableTest.class)
 * @author wangxinchun
 *
 */
public class SynchronizedStatic implements Runnable {

	private static boolean flag = true;

	private static synchronized void testSyncMethod() { // 注意static修饰的同步方法,监视器:SynchronizedStatic.class
		for (int i = 0; i < 100; i++) {
			try {
				Thread.sleep(100);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			System.out.println("testSyncMethod:" + i);
		}
	}

	private void testSyncBlock() {
		synchronized (SynchronizedStatic.class) { // 显示使用获取class做为监视器.它与static synchronized method隐式获取class监视器一样.
			for (int i = 0; i < 100; i++) {
				try {
					Thread.sleep(100);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				System.out.println("testSyncBlock:" + i);
			}
		}
	}

	public void run() {
		// flag是static的变量.所以,不同的线程会执行不同的方法,只有这样才能看到不同的锁定效果.
		if (flag) {
			flag = false;
			testSyncMethod();
		} else {
			flag = true;
			testSyncBlock();
		}
	}

	public static void main(String[] args) {
		ExecutorService exec = Executors.newFixedThreadPool(2);
		SynchronizedStatic rt = new SynchronizedStatic();
		SynchronizedStatic rt1 = new SynchronizedStatic();
		exec.execute(rt);
		exec.execute(rt1);
		exec.shutdown();
	}
}

以上代码输出的结果是一个线程先执行,然后另外一个线程执行,输出是有序的:
testSyncMethod:0
testSyncMethod:1
testSyncMethod:2
testSyncMethod:3
testSyncMethod:4
testSyncMethod:5

如果去掉testSyncMethod 的静态方法,两个线程输出结果将是混乱在一起的(线程不再锁定同一对象):
testSyncMethod:0
testSyncBlock:0
testSyncMethod:1
testSyncBlock:1
testSyncMethod:2
testSyncBlock:2
testSyncMethod:3


下面这个案例是上个案例的翻版(输出将是乱序的)
请大家体会:
package com.horizon.thread.classLock;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * 
 * synchronized (RunnableTest.class)
 * 和 synchronized (this.getClass()) 是同等的
 * @author wangxinchun
 *
 */
public class SynchronizedStatic3 implements Runnable {

	private static boolean flag = true;

	private static synchronized void testSyncMethod() { // 注意static修改的同步方法,监视器=class
		for (int i = 0; i < 100; i++) {
			try {
				Thread.sleep(10);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			System.out.println("testSyncMethod:" + i);
		}
	}

	private  void  testNotSyncBlock() {
		synchronized (this) { // 显示当前对象做为监视器
			for (int i = 0; i < 100; i++) {
				try {
					Thread.sleep(10);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				System.out.println("testNotSyncBlock:" + i);
			}
		}
	}

	public void run() {
		// flag是static的变量.所以,不同的线程会执行不同的方法,只有这样才能看到不同的锁定效果.(事实上此处是存在:race 条件)
		if (flag) {
			flag = false;
			testSyncMethod();
		} else {
			flag = true;
			testNotSyncBlock();
		}
	}

	public static void main(String[] args) {
		ExecutorService exec = Executors.newFixedThreadPool(2);
		SynchronizedStatic3 rt = new SynchronizedStatic3();
		SynchronizedStatic3 rt1 = new SynchronizedStatic3();
		exec.execute(rt);
		exec.execute(rt1);
		exec.shutdown();
	}
}
分享到:
评论

相关推荐

    synchronized枷锁实例

    **类锁(Class Lock)** 类锁是通过类的Class对象实现的,当一个线程访问类的静态 synchronized 方法或同步代码块时,就会获取到该类的Class对象的锁。所有对该类静态成员的访问都会被这把锁保护。例如: ```java ...

    Java对象锁和类锁全面解析(多线程synchronize

    与对象锁不同,类锁锁定的是类的Class对象,这意味着所有实例共享同一把锁。当一个线程进入`synchronized`修饰的静态方法或代码块时,它会获取到类的锁,其他线程若尝试执行相同操作,会被阻塞直至锁被释放。 `...

    [Android][同一对象不同实例同步操作一个目标]

    标题和描述提到的“同一对象不同实例同步操作一个目标”是指在多个线程实例中,它们都对同一个对象进行操作,这时就需要用到类锁(Class Lock)来确保线程安全。 类锁是Java中的一种同步机制,它基于Java的...

    一个关于封装了互斥锁的类实例

    在这个实例中,我们讨论的是一个已经封装了互斥锁的类,它简化了锁的管理和使用流程,使得开发者在实际应用中更加便捷。 互斥锁的工作原理是,当一个线程获得了锁,其他试图获取该锁的线程将被阻塞,直到持有锁的...

    c#lock 演示代码

    `this`作为锁对象,意味着同一实例的任何`lock`块都会互斥执行,防止了两个线程同时增加计数器的情况。 然而,需要注意的是,`lock`的对象必须是引用类型,且在同一时间只能有一个线程能获取到这个锁。如果两个`...

    简单读写锁实例代码

    在这个例子中,我们定义了一个名为`RWLock`的类,包含了四个成员函数:`lock_read`、`unlock_read`、`lock_write`和`unlock_write`。`std::shared_timed_mutex`用于实现读锁,而`std::mutex`则用于实现写锁。`...

    大厂真题之字节跳动-Java初级

    - 代码块(对象锁与类锁均可); 2. Lock 采用 lock()对代码加锁,unlock()进行解锁 参考文章:https://blog.csdn.net/yx0628/article/details/79086511 2、怎么利用反射获取类中的对象? 1. 获取 Class 对象 2. ...

    c#线程 lock用法

    然而,需要注意的是,过度使用`lock`可能导致死锁和性能下降,因此在编写多线程代码时,应尽量减少锁的使用,并考虑其他同步机制,如`Monitor`、`Mutex`、`Semaphore`或`Interlocked`类,根据具体场景选择最适合的...

    C#中lock用法详解

    1. **不要使用值类型作为锁**:因为值类型在装箱过程中会产生不同的对象实例,所以使用`lock(1)`或`lock((object)1)`是无效的,多个线程可能不会被阻止进入代码块。 2. **避免锁定公共类型或字符串**:锁定字符串...

    一个简单的java类,说明了锁的粒度

    1. **类级别锁(Class-Level Lock)**:当`synchronized`修饰静态方法或静态代码块时,锁住的是整个类的Class对象。这意味着,无论实例化了多少个对象,只有一个线程可以执行静态同步代码,适用于所有实例共享的资源...

    对象池的一个小例子

    这段代码定义了一个通用的对象池类 `TObjectPool`,该类负责管理对象的创建、锁定和解锁等操作,并且维护了一系列用于统计和管理的数据成员。 ##### 2. 对象池项 (TPoolItem) `TPoolItem` 是一个内部类,用于封装...

    继承Thread类构造多线程实例

    - 当我们创建一个新的类继承自`Thread`时,这个类的实例就是线程对象。我们需要重写`Thread`类的`run()`方法,将线程需要执行的任务放入其中。 - 实例化这个类后,调用`start()`方法会启动新线程,`start()`内部会...

    java 多线程锁的解释 实例

    Java中的锁主要分为两大类:内置锁(也称为监视器锁)和显式锁。内置锁通过`synchronized`关键字来实现,而显式锁则通过`ReentrantLock`等类来实现。 ##### 1. 内置锁(Synchronized) `synchronized`关键字是Java...

    Hibernate:不容易理解的 lock 和 merge.docx

    在 Hibernate 框架中,`lock` 和 `merge` 是两个重要的操作,它们涉及到对象的状态管理和事务控制。本文将详细解析这两个概念及其在实际应用中的作用。 首先,`lock` 方法是 Hibernate 提供的一个机制,用于在不同...

    万能对象池【C#实现】

    在C#中,我们可以使用类和泛型来实现一个万能对象池。下面是一个简单的实现框架: ```csharp public class ObjectPool&lt;T&gt; where T : class, new() { private Stack&lt;T&gt; _pool = new Stack(); private int _maxSize...

    单例代码

    单例模式是软件设计模式中的一种,它保证一个类只有一个实例,并提供一个全局访问点。在多线程环境中,确保单例的唯一性是至关重要的,以防止出现多个实例导致的资源冲突或状态不一致。这里我们将深入探讨单例模式的...

    记录redisson实现redis分布式事务锁

    在使用Redisson实现分布式锁时,我们需要创建一个RedissonClient实例,这通常在Spring Boot应用中通过配置类来完成。首先,在`application.yml`或`application.properties`中配置Redis连接信息,例如: ```yaml ...

    线程同步的理解

    对象实例锁确保了同一时刻只有一个线程能访问特定实例的方法,而类锁则确保所有线程在调用类的静态方法时按照一定的顺序执行,避免了数据混乱。理解并合理运用这些同步机制是编写安全、高效的多线程Java程序的关键。

    redis分布式锁使用实例.rar

    通过学习和实践这个“redis分布式锁使用实例”,你可以深入理解如何在实际项目中使用 Redis 和 Redisson 来实现高效且可靠的分布式锁,这对于处理分布式系统中的并发控制至关重要。同时,这也为你提供了设计和实现...

    C#锁(lock)的练习-模拟多客户端购票example

    这里的`object`是一个引用类型,通常是一个私有静态对象,这样可以确保不同实例之间的锁不会相互影响。在临界区内,只有获得锁的线程才能执行代码,其他线程会被阻塞,直到当前线程退出临界区,锁被释放。 在"模拟...

Global site tag (gtag.js) - Google Analytics