栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

synchronized 关键字用法

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

synchronized 关键字用法

synchronized 关键字最主要的三种使用方式:

1.修饰实例⽅法: 作⽤于当前对象实例加锁,进⼊同步代码前要获得当前对象实例的锁。

synchronized void method() {
 //业务代码
}

2.修饰静态⽅法: 也就是给当前类加锁,会作⽤于类的所有对象实例 ,进⼊同步代码前要获得当
前 class 的锁。因为静态成员不属于任何⼀个实例对象,是类成员( static 表明这是该类的⼀个
静态资源,不管 new 了多少个对象,只有⼀份)。所以,如果⼀个线程 A 调⽤⼀个实例对象的
⾮静态 synchronized ⽅法,⽽线程 B 需要调⽤这个实例对象所属类的静态 synchronized ⽅法,
是允许的,不会发⽣互斥现象,因为访问静态 synchronized ⽅法占⽤的锁是当前类的锁,⽽访
问⾮静态 synchronized ⽅法占⽤的锁是当前实例对象锁。

synchronized void staic method() {
 //业务代码
}

3.修饰代码块 :指定加锁对象,对给定对象/类加锁。 synchronized(this|object) 表示进⼊同步代码
库前要获得给定对象的锁。 synchronized(.class) 表示进⼊同步代码前要获得当前 class 的锁

synchronized(this) {
 //业务代码
}

总结:

synchronized 关键字加到 static 静态⽅法和 synchronized(class) 代码块上都是是给 Class
类上锁。synchronized 关键字加到实例⽅法上是给对象实例上锁。尽量不要使⽤ synchronized(String a) 因为 JVM 中,字符串常量池具有缓存功能。 双重检验锁方式实现单例模式的原理

双重校验锁实现对象单例(线程安全)

public class Singleton {
 	private volatile static Singleton uniqueInstance;
 	
 	private Singleton() {
 	}
 	
 	public static Singleton getUniqueInstance() {
 	//先判断对象是否已经实例过,没有实例化过才进⼊加锁代码
 		if (uniqueInstance == null) {
 		//类对象加锁
 			synchronized (Singleton.class) {
 		if (uniqueInstance == null) {
 			uniqueInstance = new Singleton();
 			}
 		}
 	}
	 return uniqueInstance;
 }
}

另外,需要注意 uniqueInstance 采⽤ volatile 关键字修饰也是很有必要。uniqueInstance 采⽤ volatile 关键字修饰也是很有必要的, uniqueInstance = new Singleton(); 这段代码其实是分为三步执⾏:

    为 uniqueInstance 分配内存空间初始化 uniqueInstance将 uniqueInstance 指向分配的内存地址

但是由于 JVM 具有指令重排的特性,执⾏顺序有可能变成 1->3->2。指令重排在单线程环境下不
会出现问题,但是在多线程环境下会导致⼀个线程获得还没有初始化的实例。例如,线程 T1 执
⾏了 1 和 3,此时 T2 调⽤ getUniqueInstance () 后发现 uniqueInstance 不为空,因此返回
uniqueInstance ,但此时 uniqueInstance 还未被初始化。使⽤ volatile 可以禁⽌ JVM 的指令重排,保证在多线程环境下也能正常运⾏。 synchronized 关键字和 volatile 关键字的区别

synchronized 关键字和 volatile 关键字是两个互补的存在,⽽不是对⽴的存在!

volatile 关键字是线程同步的轻量级实现,所以 volatile 性能肯定⽐ synchronized 关键字要好。但是 volatile 关键字只能⽤于变量⽽ synchronized 关键字可以修饰⽅法以及代码块。volatile 关键字能保证数据的可⻅性,但不能保证数据的原⼦性。 synchronized 关键字两
者都能保证。volatile 关键字主要⽤于解决变量在多个线程之间的可⻅性,⽽ synchronized 关键字解决
的是多个线程之间访问资源的同步性。 ThreadLocal

通常情况下,我们创建的变量是可以被任何⼀个线程访问并修改的。如果想实现每⼀个线程都有
自己的专属本地变量该如何解决呢? JDK 中提供的 ThreadLocal 类正是为了解决这样的问题。
ThreadLocal 类主要解决的就是让每个线程绑定⾃⼰的值,可以将 ThreadLocal 类形象的⽐喻成
存放数据的盒⼦,盒⼦中可以存储每个线程的私有数据。
如果你创建了⼀个 ThreadLocal 变量,那么访问这个变量的每个线程都会有这个变量的本地副
本,这也是 ThreadLocal 变量名的由来。他们可以使⽤ get()和 set() ⽅法来获取默认值
或将其值更改为当前线程所存的副本的值,从⽽避免了线程安全问题。

举个简单的例⼦:
⽐如有两个⼈去宝屋收集宝物,这两个共⽤⼀个袋⼦的话肯定会产⽣争执,但是给他们两个⼈每
个⼈分配⼀个袋⼦的话就不会出现这样的问题。如果把这两个⼈⽐作线程的话,那么ThreadLocal 就是⽤来避免这两个线程竞争的。

ThreadLocal 原理
public class Thread implements Runnable {
 ......
//与此线程有关的ThreadLocal值。由ThreadLocal类维护
ThreadLocal.ThreadLocalMap threadLocals = null;
//与此线程有关的InheritableThreadLocal值。由InheritableThreadLocal类维护
ThreadLocal.ThreadLocalMap inheritableThreadLocals = null;
 ......
}

从上⾯ Thread 类 源代码可以看出 Thread 类中有⼀个 threadLocals 和 ⼀个inheritableThreadLocals 变量,它们都是 ThreadLocalMap 类型的变量,我们可以把ThreadLocalMap 理解为 ThreadLocal 类实现的定制化的 HashMap 。默认情况下这两个变量都是 null,只有当前线程调⽤ ThreadLocal 类的 set 或 get ⽅法时才创建它们,实际上调⽤这两个⽅法的时候,我们调⽤的是 ThreadLocalMap 类对应的 get() 、 set() ⽅法。

ThreadLocal 类的 set() ⽅法:

public void set(T value) {
 	Thread t = Thread.currentThread();
 	ThreadLocalMap map = getMap(t);
 	if (map != null)
 		map.set(this, value);
	 else
 		createMap(t, value);
 }
 	ThreadLocalMap getMap(Thread t) {
 	return t.threadLocals;
 }

通过上⾯这些内容,我们⾜以通过猜测得出结论:最终的变量是放在了当前线程的ThreadLocalMap 中,并不是存在 ThreadLocal 上, ThreadLocal 可以理解为只是 ThreadLocalMap 的封装,传递了变量值。 ThrealLocal 类中可以通过 Thread.currentThread()获取到当前线程对象后,直接通过 getMap(Thread t) 可以访问到该线程的 ThreadLocalMap 对象。

ThreadLocal 内部维护的是⼀个类似 Map 的 ThreadLocalMap 数据结构, key 为当前对象的 Thread 对象,值为 Object 对象。

ThreadLocalMap(ThreadLocal firstKey, Object firstValue) {
 ......
}

⽐如我们在同⼀个线程中声明了两个 ThreadLocal 对象的话,会使⽤ Thread 内部都是使⽤仅有
那个 ThreadLocalMap 存放数据的, ThreadLocalMap 的 key 就是 ThreadLocal 对象,value 就是
ThreadLocal 对象调⽤ set ⽅法设置的值。

ThreadLocalMap 是 ThreadLocal 的静态内部类。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/759876.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号