01.并发编程之synchronized

1、线程安全概念

当多个线程访问某一个类(对象或方法)时,这个类始终能表现出正确的行为,那么这个类(对象或方法)就是线程安全的。
synchronized加锁的代码块称为“互斥区”或“临界区”。
锁竞争的问题,导致CPU使用率非常高,性能非常慢,宕机。
对象锁与类锁(静态方法上加synchronized,类独占)。

2、对象锁的同步与异步

同步的需要线程去排队
同步的目的是为了线程安全,对于线程安全来说,需要满足:

(1)原子性(同步)

A线程先持有object对象的Lock锁,B线程如果在这个时候调用对象中的同步(synchronized)方法,则需要等待,也就是同步。
A线程先持有object对象的Lock锁,B线程可以以异步的方式调用对象中的非同步方法。

(2)可见性

3、脏读

对于对象的同步和异步的方法,设计自己的程序时候,要考虑业务问题的整体,不然会出现数据不一致的错误。
ACID:Oracle一致性读,9:00一刻的数据,发起select查询,即使9:10分才查出来,9:05进行了更新,9:10分查询时,发现undo有变化了,会去undo中查询出来,绝对不会查询新值。如果客户端并发导致undo丢失了,会抛snapshot too old

4、synchronized锁重入

当一个线程得到一个对象的锁后,再次请求此对象时是可以再次得到该对象的锁。(父子继承关系也可以)。
多线程处理多个任务中,要求同时成功或同时失败时,如中间出现异常时,可以printstackStrace打印日志不进行中断,或者throw new RuntimeException进行中断。
碰到异常,锁会立即释放,其他线程会进入,需要正确处理异常。如果对象由于线程未正确而释放了锁,可能会对后续的对象执行都是错误的处理逻辑。
PS:数据库中的存储过程,beginend中才可以加exception when

5、不要使用"abc"这种作为锁对象

常量池中会造成死循环;可以使用new String("abc")
private String lock="lock"作为锁对象后,不能进行更改该lock,修改后,会引发锁释放。
但如果是对象作为锁对象,修改属性不影响锁的持有。

推荐阅读更多精彩内容