一丶线程的同步

来源:互联网 发布:手机淘宝店铺装修 编辑:程序博客网 时间:2024/06/06 10:23

何为线程安全:

当多个线程访问某一个类,该类都能表现出一个正确的行为,即为线程安全。


等待通知模型:线程间协作:wait、notify、notifyAll


synchronized是Java中的关键字,是一种同步锁。使用场景有以下几种: 
1. 修饰一个代码块,被修饰的代码块称为同步语句块,其作用的范围是大括号{}括起来的代码,作用的对象是调用这个代码块的对象; 
2. 修饰一个方法,被修饰的方法称为同步方法,其作用的范围是整个方法,作用的对象是调用这个方法的对象; 
3. 修饰一个静态的方法,其作用的范围是整个静态方法,作用的对象是这个类的所有对象; 
4. 修饰一个类,其作用的范围是synchronized后面括号括起来的部分,作用主的对象是这个类的所有对象。

细节:

1.多个synchronized方法之间相互调用,线程安全的
父子继承时都用synchronized修饰,父子相互调用时,也是线程安全的

2.遇到异常时会释放锁,要想不释放可以进行catch

3.synchronized代码块,针对一个字符串加锁,那么不要在代码块里面修改这个字符串,否则锁改变了,其他线程就能进来了

但是如果对对象加锁,对象内的属性变了,不会改变锁的

注意:

一个类中在static的方法上面加synchronized,这个锁是类级别的锁,所有对象共享。否则为对象级别的锁

如果一个类中有多个非static方法被synchronized修饰,那么这些方法同时只能被一个线程访问。不能被并行访问。



优化:

synchronized里面的代码越少越好,减少锁的粒度


ReentrantLock(可以替代sync,更为灵活):

获取非公平锁(效率低:等待时间长的不一定先得到锁):Lock lock= new ReentrantLock();

获取公平锁(效率高):Lock lock= new ReentrantLock(true);

开始:lock.lock();

结束(必须释放,遇到异常时也要手动释放,一般放在finally):lock.unlock();

可以利用conditon精确的控制那些线程睡着或醒来,提高效率



ReentrantLock和synchornized区别:

1.前者可以进行尝试性的lock(boolean flag = lock.tryLock(time))time指定尝试的时间,后者只会死等

2.利用lock.lockInterruptibly()打断正在等待锁的进程,抛出InterruptedException异常

3.synchronized和wait,notify/nitifyAll使用 ReentrantLock和await,singal/singalAll一起使用(Lock的await/singal 和 Object的wait/notify )


ThreadLocal:线程的局部变量,不同的ThreadLocal里面的变量可以认为是两个不同的对象


互斥锁与信号量的作用与区别