死磕高并发与网络编程学习笔记及总结-设计模式(二)

第二阶段:多线程设计模式详细介绍

2.Immutable 想破坏它也没办法

3.Guarded Suspension 要等我准备好哦

4.Balking 不需要的或就算了

5.Producer-Consumer 我来做,你来用

6.Read-Write Lock 大家想看就看吧,不过看的时候不能写哦

7.Thread-Per-Message 这个工作交给你了

8.Worker Thread 等到工作来,来了就工作

9.Future 先给你张提货单

10.Two-Phase Termination 快把玩具收拾好,去睡觉吧

11.Thread-Specific Storage 每个线程的保管箱

12.Active Object 接受异步消息的主动对象

1、You may  not know the singleton design pattern

Single thread execution 能通过这座桥的,只有一个人

public class Singleton {
	//饿汉式(静态常量)[可用] code easy,but can't lazy load
	private static final Singleton INSTANCE = new Singleton();
	private Singleton() {}
	public static Singleton getInstance() {
		return INSTANCE;
	}
}
public class Singleton {
    //饿汉式(静态代码块)[可用] can't lazy load
    private static Singleton instance;
    static{
	    instance = new Singleton();
    }
    private Singleton() {}
    public static Singleton getInstance() {
	    return instance;
    }
}
public class Singleton {
	//懒汉式(线程不安全)[不可用,多线程的情况下,一个线程进入if语句中,还未执行下面代码,另外一个线程同样进入,导致产生多个实例]
	private static Singleton instance;
	private Singleton() {}
	public static Singleton getInstance() {
		if(null == instance)
			instance = new Singleton();
		return instance;
	}
}
public class Singleton {
	private static Singleton instance;
	private Singleton() {}
	public static Singleton getInstance() {
		if(null == instance) {
			synchronized (Singleton.class) {
				instance = new Singleton();
			}
		}
		return instance;
	}
}
public class Singleton {
	private static volatile Singleton instance;
	private Singleton() {}
	public static Singleton getInstance() {
		if(null == instance) {
			synchronized (Singleton.class) {
				if(null == instance)
					instance = new Singleton();
			}
		}
		return Singleton.instance;
	}
}
public class Singleton {
	private Singleton() {}
	private static class InstanceHolder{
		private final static Singleton instance = new Singleton();
	}
	public static Singleton getInstance() {
		return InstanceHolder.instance;
	}
}
public class Singleton {
	private Singleton() {}
	//枚举类型时线程安全的,并且它的构造函数只会被加载一次
	private enum SingletonEnum{
		INSTANCE;
		private final Singleton instance;
		SingletonEnum(){
			instance = new Singleton();
		}
		public Singleton getInstance() {
			return instance;
		}
	}
	public static Singleton getInstance() {
		return SingletonEnum.INSTANCE.getInstance();
	}
}

 2、WaitSet in synchronized monitor

wait set 线程的休息室,放到monitor中(锁)

WaitSet(线程休息室)

3、Cpu&Cpu Cache&Mian Memory&Data Bus&Cache

application-t1 写入CPU--->共享变量--->cache(CPU高速缓存一致性协议Inter的MESI)--->main memory
总线(数据总线,地址总线,控制总线)

cpu cache cache line

内存有2部分、RAM、ROM

CPU的寄存器、CPU指令

汇编、MOV、JMP、ADD

4、The volatile key word in deep

volatile可以保证内存的可见性,有顺性。不可以保证原子性

JMM的大致结构(java 内存模型)
缓存一致性协议
指令重排序
happens-before规则
并发编程的三大要素AVO(原子性(要么都成功,要么都失败),可见性,有序性)
volatile关键字的作用(可见性,有序性,不能保证原子性)
volatile的使用场景1)状态量标记2)屏障前后的一致性

volatile答疑
1、保证可见性:高速缓存的一致性协议
2、保证有序性:内存屏障
1、标志位
2、防止重排序(状态判断)
类一个共享资源ShareData    
所有的基本类型赋值以及读取都是原子性的
宽子word 4 byte =int

i=1;
i=1+1;
cpu1->main memory->i->cache i+1 ->cache(2) ->main memory(2)
cpu2->main memory->i->cache i+1 ->cache(2) ->main memory(2)

1)给数据总线加锁
总线(数据总线,地址总线,控制总线)
LOCK

2)CPU高速缓存一致性协议
Inter的MESI

核心思想
1)当CPU写入数据的时候,如果发现该变量被共享(也就是说,在其他cpu中也存在该变量的副本),会发出一个信号,通知其他cpu该变量婚车无效
2)当其他cpu访问该变量的时候,重新到助内存进行获取

并发编程中三个重要的概念(AVO)
1)A原子性 一个操作或者多个操作,【要么都成功,要么都失败】,中间不能由于任何的因素中断
2)V可见性
3)O有序性
(顺序性):重排序,只要求最终一致性

i=1;
flag = true;

重排序只要求最终一致性

volatile boolean init;
--------------Thread -1----------------
obj = createObj()    1;
init = true;     2;

--------------Thread -2----------------
whle(!init){
    sleep();
}
useTheObj(obj);
-----------------------------------------

Java内存模型以及CPU缓存不一致的问题

1、原子性
对基本数据类型的变量读取和赋值是保证原子性的,要么都成功,哟么都失败,这些操作是不可被中断

i=10;
cache 10,memory 10;

a=10;    原子性
b=a;    不满足,1.read a;2.assign to b;
c++;    不满足,1.read c;2add;3assign to c;
c=c+a;    不满足,1.read c;2add;3assign to c;

2、可见性
使用volatile关键字保证可见性

3、有序性
happens-before relationship(重排序规则)
1)代码执行顺序,编写在前面的发送在编写在后面的
2)uolock必须发生在lock之后
3)volatile修饰的变量,对该变变量,先写后读
4)传递规则,操作A先于B,B先于C,那么A肯定先于C
5)线程的启动规则,start方法肯定先于线程run
6)线程的中断规则,interrupt这个动作,必须发生在捕获该动作之前
7)对象销毁规则,初始化必须发生在finalize之前
8)线程终结规则,所有的操作都发生在线程死亡之前那

try{
    lock.lock();
}finally{
    lock.unlock();
}

volatile关键字
一旦一个共享变量被volatile修饰,具备俩层语义
1)保证了不同线程间的可见性
2)禁止对其进行重排序,也就是保证了有序性
3)并未保证原子性

package com.topxin.designpattern.chapter3;
public class VolatileTest {	
	//volatile可以保证内存可见性,有顺性。不可以保证原子性
	private /* volatile */ static int INIT_VALUE = 0;	
	private final static int MAX_LIMIT = 50;	
	public static void main(String[] args) {		
		new Thread(()->{
			int localValue = INIT_VALUE;
			while(localValue < MAX_LIMIT) {
				if(localValue != INIT_VALUE) {
					System.out.printf("The value update to [%d]\n",INIT_VALUE);
					localValue = INIT_VALUE;
				}
			}
		},"READER").start();		
		new Thread(()->{
			int localValue = INIT_VALUE;
			while(INIT_VALUE < MAX_LIMIT) {
				System.out.printf("Update the value to [%d]\n",++localValue);
				INIT_VALUE = localValue;
				try {
					Thread.sleep(500);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		},"UPDATER").start();
	}
}
read from main memory INIT_VALUE->10
INIT_VALUE=10+1
INIT_VALUE=11

1)保证重排序的是不会把后面的指令放到屏障的前面,也不会把前面的放到后面
2)强制对缓存的修改操作立刻写入主存
3)如果是写操作,它会导致其他CPU中的缓存失效

volatile的使用场景

1)状态量标记

volatile boolean start = true;
while(start){}
void close(){start = false;}

2)屏障前后的一致性

总结

cpu的大致结构    application-t1 写入CPU--->共享变量--->cache(CPU高速缓存一致性协议Inter的MESI)--->main memory
        总线(数据总线,地址总线,控制总线)
JMM的大致结构(java 内存模型)
缓存一致性协议
指令重排序、
happens-before规则
并发编程的三大要素AVO(原子性(要么都成功,要么都失败),可见性,有序性)
volatile关键字的作用(可见性,有序性,不能保证原子性)

volatile的使用场景1)状态量标记2)屏障前后的一致性

5、Java Class Loader
6、Observer to monitor the Thread lifecycle

Observerable/Subject主题/事件源(state)    Observer事件源的被通知者

7、Single Thraded Execution design patten

 

 READWRITE
READNY
ERITEYY

8、Immutable design pattern    

不可变对象 final修饰  没有write 只有read

避免加锁,提高效率

不可变对象一定是线程安全的    里面的任务属性或者引用类型的属性都不能被修改
可变对象不一定是不安全的    StringBuffer

J2EE servlet 不是线程安全的
struts1.x Acton不是线程安全的
struts2.x Action是线程安全

9、Guarded Suspension  

担保

被保护的,先放在队列里,之后一个个做

A在厨房做早餐
B是快递员,墙门,说你的快递来了,要求开门

Reqeust -> Tomcat httpServer ->doing
Request ->Tomcat httpServer
    Queue

10、Balking design pattern

酒吧、服务生、轮值服务生,模拟word文件,ctrl+s保存,word自动保存

11、Producer-Consumer

12、Read-Write Lock design Pattern

waitset
wait
notifyAll
solution
BooleanLock
syschronized

->Data
    read    
    write
1. read other thread wail enter to the waitset
2. read write 锁分离
concern conflict
1.read read 并行化
2.read write 不允许
3.write write 不允许

ReadWriteLock design pattern
Reader-Writer design pattern

13、Thread-Per-Message Design Pattern

线程池

14、Worker Thread Design Pattern

屏蔽了worker

15、Future

票据,结果有了过一会去拿,留下地址

Future            ->代表的是未来的一个凭据
FutureTask        ->将你的调用逻辑进行隔离
FutureService        ->桥接 Future  和 FutureTask

16、Two-Phase Termination Design Pattern    

2个阶段终结

17、The Thread-Specific Storage  

线程保险箱,高效,线程安全,用途广,(可以解决上下文传值的问题)

线程保险箱,上下文,Map,用线程作为key

ThreadLocal    始终以当前线程作为key值

private static final ThreadLocal<Context> threadLocal = new ThreadLocal<Context>() {
    @Override
    protected Context initialValue() {
        return new Context();
    }
};

总结
invoke一个方法
Future        提货单,注入一个函数,线程间的通讯
Suspenion        先挂起来,有时间了一个一个做,线程间的通讯
example
balking     放弃 

18、Active Objects

19、Count Down  Design Pattern

所有东西都完成在来,用通知方式实现了LocalThread

20、JMM-Java Memory Model

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值