第二章对象及变量的并发访问

今天这一章应该是看不完的,把现在看的一部分先记录进来,剩下的部分之后看完再加。

首先说明了“非线程安全”问题存在于实例变量中,如果是方法内部的私有变量,则不存在“非线程安全”问题。

这一章主要是讲的并发访问问题,处理并发问题可以使用synchronized同步方法,列举了三种类型的例子:

    1、两个线程修改同一个实例变量,并且线程都不加synchronized,会出现线程安全问题。

    2、两个线程修改同一个实例变量,其中一个线程加了synchronized,会出现线程安全问题。

    3、两个线程修改同一个实例变量,两个线程都加了synchronized,不会出现线程安全问题。

synchronized是对象锁,也就是说当一个有synchronized方法的类被创建了多个对象,每个对象都会有一把锁,多个线程访问这多个对象,是异步进行访问。

脏读:多个线程操作一个对象的实例变量时,有可能会出现脏读,就是在读数据的过程中,数据被改了。

锁重入:指的是在一个synchronized方法内,去调用相同对象锁的别的方法,可以直接获取锁。子类可以通过锁重入调用父类的synchronized方法。

出现异常,锁自动释放。子类重写父类synchronized方法,不会自动去继承synchronized方法,还需要自己去加。

synchronized同步代码块:由于synchronized方法同步,如果放在方法上就会使方法阻塞,但是方法里面不一定所有的内容都会存在线程安全问题,所以可以使用synchronized代码块,把可能出现问题的部分的代码进行阻塞,这样可以提高运行效率。

synchronized(对象)区分同步是否生效,主要就是判断括号中的对象是否相等,这个相等不是值相等,是地址值相等。

synchronized public static void test()和synchronized public void test()同步的锁是不一样的,带有static的方法上使用的事类锁(class锁),没有static的方法是对象锁(object锁)

类锁加在代码块上是public static void print(){synchronized(Class.class){System.out.println}}

使用String类型字符串作为锁时注意,String具有常量池缓存的功能,两个“AA”就是一把锁,而两个new Object()是两把锁。

下面是一个关键点:

有两个线程(线程1,线程2)需要竞争同一把锁,他们同时开启,先抢到锁的先执行完,直到释放锁,另一个线程才会接着执行。正常情况下是这样,如果线程1先拿到锁,在执行过程中将锁的值修改了,这样结果会发生什么变化呢?

1、他们同时开始执行的,首先线程1拿到锁且执行到修改了锁那里,这个时候线程2需要的锁还是之前的,所以线程2并不会执行,还是会等到线程1释放完锁才会执行。

2、如果线程1线执行且拿到锁并修改值,但是并未执行完,这个时候线程2开始执行,那么线程2就会和线程1异步执行了,线程2需要的锁会发生变化。


volatile:主要作用是使变量在多个线程间可见。使用场景就是可以在多个线程中感知实例变量被更改了,并且可以获得最新的值使用,也就是用多线程读取共享变量时可以获得最新的值使用。

服务器在运行时会有一个公共堆栈和一个线程的私有堆栈,服务器为了提高效率,通常会去私有堆栈获取变量值,当公共堆栈的值发生改变时就造成了数据的不一致,而在变量上加了volatile可以强制让线程去读取公共内存中的值,这样就让实例变量在多个线程中保证了可见性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值