再谈synchronized

再谈synchronized

 

a.    synchronized作用于方法,二种作用域情况:

 

1)  synchronized 作用于类的对象实例的方法

一个对象中有多个synchronized方法时,当线程1已经访问了这个对象中的任何一个synchronized的方法,线程2不能访问这个对象的任何一个synchronized方法了。但是如果线程2访问的是这个类的另外一个对象中的synchronized方法的话是没有关系的。

2)  synchronized 作用于类的方法

synchronized static aStaticMethod{}防止多个线程同时访问这个类中的synchronized static 方法。它可以对类的所有对象实例起作用。

 

b.    synchronized 作用于代码块

      synchronized(this){/*区块1*/}//它的作用域是当前对象;代码块在方法内,虽然这个方法不是synchronized,但是当线程1在访问这个块的时候,线程2就不能再访问这个对象中的其他的任何的synchronized方法和synchronized(this){/*区块1*/}的代码块。

       Object ob1=”resource1”;

       Object ob2=”resource2” ;

      

       synchronized(ob1){/*区块2*/}//作用域为ob1,可以理解为 区块2被称ob1lock锁住了。

       synchronized(ob2){/*区块3*/}//作用域为ob2,可以理解为 区块3被称ob2lock锁住了。

### HashMap 多线程死循环问题的原因及解决方案 #### 死循环问题的原因 在多线程环境下,HashMap 可能出现死循环的问题,尤其是在 JDK1.7 及更早版本中。这种问题的核心原因在于 HashMap 的扩容机制与链表插入方式的结合。 在 JDK1.7 中,HashMap 使用头插法将元素插入到链表中。当多个线程同时进行 `put` 操作时,如果触发了扩容操作(即 `resize`),每个线程可能会独立地尝试重新哈希并重新分布桶中的元素。由于头插法的顺序反转特性,多个线程并发操作时可能导致链表形成环形结构,从而在后续的查找操作中进入死循环[^2]。 此外,HashMap 本身不是线程安全的数据结构,多个线程同时对 HashMap 进行修改操作(如插入、删除)可能导致数据不一致或内部结构异常,进一步加剧了死循环的风险[^4]。 #### 解决方案 ##### 使用 `ConcurrentHashMap` 为了在多线程环境下保证线程安全,推荐使用 `ConcurrentHashMap`。与 `HashMap` 不同,`ConcurrentHashMap` 通过分段锁(JDK1.7)和 CAS 操作(JDK1.8 及之后)来提供高效的并发性能[^2]。 在 JDK1.8 中,`ConcurrentHashMap` 进一步优化了扩容机制,避免了链表头插法带来的死循环问题。它通过将链表转换为红黑树来提高性能,并且在并发操作时能够更好地处理哈希冲突,确保线程安全[^2]。 以下是 `ConcurrentHashMap` 的简单使用示例: ```java import java.util.concurrent.ConcurrentHashMap; public class ConcurrentHashMapExample { public static void main(String[] args) { ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<>(); // 线程安全的 put 操作 map.put("key1", 1); map.put("key2", 2); // 线程安全的 get 操作 Integer value = map.get("key1"); System.out.println("Value for key1: " + value); } } ``` ##### 使用 `Collections.synchronizedMap` 如果不想使用 `ConcurrentHashMap`,也可以通过 `Collections.synchronizedMap` 方法将普通的 `HashMap` 包装成线程安全的版本。这种方式虽然简单,但性能不如 `ConcurrentHashMap`,因为它会对整个 Map 进行加锁。 ```java import java.util.Collections; import java.util.HashMap; import java.util.Map; public class SynchronizedMapExample { public static void main(String[] args) { Map<String, Integer> synchronizedMap = Collections.synchronizedMap(new HashMap<>()); // 线程安全的操作 synchronizedMap.put("key1", 1); synchronizedMap.put("key2", 2); Integer value = synchronizedMap.get("key1"); System.out.println("Value for key1: " + value); } } ``` ##### 避免并发修改 在设计程序时,尽量避免多个线程同时对同一个 HashMap 进行修改操作。可以通过减少共享状态、使用局部变量或线程本地存储(ThreadLocal)等方式来降低并发冲突的概率。 #### 总结 HashMap 在多线程环境下容易出现死循环问题,主要是由于其非线程安全的设计和扩容机制的并发问题。为了解决这个问题,Java 提供了 `ConcurrentHashMap`,它通过分段锁和 CAS 操作提供了更高效的并发性能。此外,还可以使用 `Collections.synchronizedMap` 或者通过设计避免并发修改来确保线程安全。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值