例子:两个储户,到同一个银行存钱,每个人存了三次,一次100元。
1、描述银行。2、描述储户任务。
分析多线程是否存在安全隐患?
1、线程任务是否有共享数据? 2、是否多条操作共享数据的代码?
同步函数 :其实就是在函数上加上了同步关键字进行修饰。
同步的表现形式有两种:同步函数和同步代码块。
同步函数使用的锁是什么? 同步函数使用的锁是this。(会有对象调用这个函数)
函数需要被对象调用,哪个对象不重要,但是都是用this表示。
如果同步函数被static修饰呢?
static方法随着类的加载,这是不一定有该类的对象。但是一定有一个该类的字节码文件对象。这个对象简单的表示方式就是: 类名.class 。
单例模式的并发访问:
1、饿汉式:相对于多线程并发是安全的。
class Single{
private Single(){}
private static final Single s = new Single();
public static Single getInstance(){
return s;//对该类数据操作一次,如果多次操作,还是会存在安全隐患的。
}
}
2、懒汉式(延迟加载方式):在多线程并发访问时,会出现线程的安全问题。
class Single{
private Single(){}
private static final Single s = null;
public static Single getInstance(){
if(s==null){
synchronized(Single.class){
if(s==null){
s =new Single();
}return s;
}
}
}
}
加了同步就可以解决问题,无论同步函数还是同步代码块。但是效率低了,可以通过if对单例对象的双重判断形式。
同步函数和同步代码块的区别:
同步代码块使用任意对象作为锁,同步函数只能使用this作为锁。
如果说一个类中只需要一个锁,这时可以考虑同步函数,使用this,写法也简单。
如果一个类中需要读个锁,或者多个类中需要使用同一个锁,这时只能使用同步代码块。
所以,建议使用同步代码块。
多线程通信:多个线程都在处理同一个资源,但是处理的任务不一样。
多线程是启动任务并去处理数据,之前学的是任务是一样的,资源也是同一个。
典型的案例是:生产者和消费者。