ConurrentHashMap

LinkedList 线程安全版本

class Node{
	int val;
	Node next;
}
class LinkedList{

	Node head = null;
	void pushFront(int val){}
	void pushBask(int val){}
	
}

1.最简单的办法:当前链表对象( LinkedList this )
很多时候,线程之间有些是没有必要互斥的
A 线程在头插:1. 新建一个节点 2. 修改链表的head
B 线程在尾插:1. 新建一个节点 2. 修改链表最后一个节点的next
所以需要更细粒度的锁
在这里插入图片描述
使用CAS方法伪代码:

Node head=this.head;
Node node=new Node(val,head);	
//CAS成功,代表头插成功,结束
//CAS失败,表示在这之前已经有其他线程完成头插,我们重新获取head再次进行头插
while(CAS(address,head,node)==false){
	head=this.head;
	node.next=head;
}

使用CAS其实是放弃了强一致性:
A先开始头插 / B后开始头插
结果B先被调度,导致B CAS成功
B的节点就先被头插了

2 . ConturrentHashMap
在这里插入图片描述
线程安全的集合类:
Vector / HashTable(不建议使用了)
顺序表
不建议使用的原因是:每个方法都会带着一个synchronized(抢一把大锁),所以效率低
CopyOnWriteArrayList(因为是不可变对象)
读的时候不影响,一旦修改,会立刻赋值一份然后在自己的这份中做修改

List list =Collections.synchronized(new ArrayList() );
list是线程安全的,但是效率不高不建议使用

需要注意 ConcurrentHashMap不支持null作为key,hashMap是支持null作为key的。

提问:
现在已知A类是线程安全的,B类只使用了A类,问B类是线程安全的吗?

class MyClass{
	private ConcurrentHashMap=...;
public add(){
   if(map.containsKey(key)){
	  map.deleteKey(key);
       }
   }
}

这个不是线程安全的:
如果A线程发现map中存在key正准备删除,此时CPU发生调度,B线程进入,并且完成了delete操作。
现在B线程调下去,A线程再次进入就会发生删除失败。所以不是线程安全的。
所以线程安全是不会传染的。

串加工厂模式:

没有工厂的时候:
Person p=new Person();
有了工厂
Person p=PersonFactory.build();
工厂的工厂
PersonFactory pf= FactoryFactory.build();
Person p=pf.build();

作用:
加入有5000万行代码
new Person()写了800万次,分布在各个地方。
有一天,需要修改一下new Person()的方式。则需要全部修改

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章