java多线程和高并发基础(1)

多线程高并发主要是三个方面:synchronizer/同步容器/ThreadPool、executor
synchronized 锁定的不是代码块,而是堆中的对象,java的锁时记录在对象上的一个信息,有人锁定了信息就变成1,再次锁定就变成2。synchronized(this)其中的this指定的是当前类,表明锁定当前类。
同步方法和非同步方法可以同时调用,同步方法需要锁,而非同步方法不需要锁,所以就不冲突
对业务写方法加锁,对读方法不加锁容易产生脏读的问题,解决脏读的问题CopyOnWrite
一个同步方法可以调用另一个同步方法,一个线程已经拥有了某个对象的锁,再次申请的时候仍然会得到该对象的锁,也就是说synchronized获得的锁是可以重入的
使用synchronized加的锁,如果出现异常,jvm虚拟机会自动释放锁,用手动锁的时候,出现异常是不会自动释放锁的
子类的同步方法可以调父类的同步方法
synchronized作用在静态方法上时,相当于synchronized(当前类.class),锁定当前类的class对象。
synchronized的代码是原子操作,不可分
死锁:线程一先调用synchronized修饰的资源A,在调用资源B。但是线程二先调用synchronized修饰的资源B,再调用资源A。结果线程一二分别持有资源AB,导致谁也无法完成,形成死锁。
volatile 修饰变量,使其变为线程之间可见,无锁同步。volatile的作用也可以用synchronized实现,但是volatile的效率会高的很多。volatile只保证可见性,不保证原子性。而synchronized既保证可见性又保证原子性。
锁定某个对象o,如果对象o的属性改变,不影响锁的使用。如果o变成另外一个对象,则锁定的对象发生改变,应该避免锁定对象的引用变成另外的对象。因为锁的信息是记录在堆中对象上
Atomxxx具有原子性,进行简单类型的同步操作优先考虑这种方式。Atomxxx的多个方法并不构成原子性。
synchronized的优化:尽量只锁定必要的内容,即锁的粒度越细越好。
不要用字符串常量作为锁定对象 p21

如下代码中其实m1和m2方法锁定是同一个对象,可能就会造成死锁。jetty开源软件曾经出现过这类bug

String s1="Hello";
String s2="Hello";
void m1(){
synchronized(s1){
}
}
void m2(){
synchronized(s2){
}
}
只有wait释放锁,notify,sleep不释放锁。wait,notify()必须在synchronized的里面调用,调用notify启动的线程不由程序员指定,而是由CPU指定。能避免使用wait和notify就尽量避免。通过被锁住的对象调用 p22
CountDownLatch(类似的类cyclicbarrier/semaphore)门闩的使用:门闩不锁定对象 p23

创建门闩
CountDownLatch latch= new CountDownLatch(1);
门闩检测,当门闩的值为0代表成功继续向下执行
latch.await();
门闩减值
latch.countDown();

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值