多线程2.0

synchronize同步原理:

 所有对象都默认有一个单一的锁,JVM实时监控每个对象上面的锁情况,当第一次进入synchronized代码块时,就会在该代码块的对象锁上加一,当还没离开同步代码块时,其他任务线程访问该代码块时,发向对象上的锁不是0,就无法获得对象锁而处于等待阻塞状态,直到上一个任务离开时,对象锁会自动减一,直到为0了,下一个任务线程才有机会获得对象锁而执行任务


线程中的资源共享:
当多个线程访问同一共享资源时,如果不加以同步处理,很有可能使他们访问出错;例如,把你餐桌上的食物是共享资源,你正伸手去拿食物,突然食物不见了,这就造成了共享资源混乱;java提供给我们的处理的办法就是上锁:synchronized,使用该关键字把你需要的同步方法包起来,则以后有线程要访问你这段代码,就必须获得该对象实例的同步锁(此锁是java内部对象生成的,隐式提供给我们的,该类的其他对象访问这段代码还是可以的;如果同步的方法是静态方法,则要获取该类的同步锁才行),使用方法如下:
	public void test() {
     ...
     synchronized(this) {
          // todo your code
     }
     ...
}
 
此时,其效果等同于
public synchronized void test() {
     // todo your code
}



 
和同步锁相关的三个方法:wait()/notify()/sleep()
wait()表示当前线程释放同步锁,进入线程等待池,是否能够CPU,其他线程可以抢占此同步锁
notify()唤醒因为调用wait()方法而进入休眠的线程,从而使该剧线程有机会再次获得同步锁
sleep()同样也是使线程进入休眠,释放CPU,但是不释放同步锁
wait和notify必须要在synchronized代码块中才调用


与上面对应locked的方式对应有:

await() / signal()和signalAll();并且signal能实现公平的通知,而notify是随机唤醒某个线程


java5提供了新的同步方法lock和unlock:
虽然代码量比synchronized多,但控制精度更高,更准确;并发量大的时候是个不错的选择;使用也更加灵活
使用方法:
	class LockTest extends TestTemplate{     
    ReentrantLock lock=new ReentrantLock();     
    public LockTest(String _id,int _round,int _threadNum,CyclicBarrier _cb){     
        super( _id, _round, _threadNum, _cb);     
    }     
    /**   
     * synchronized关键字不在方法签名里面,所以不涉及重载问题   
     */    
    @Override    
    long getValue() {     
        try{     
            lock.lock();     
            return super.countValue;     
        }finally{     
            lock.unlock();     
        }     
    }     
    @Override    
    void sumValue() {     
        try{     
            lock.lock();     
            super.countValue+=preInit[index++%round];     
        }finally{     
            lock.unlock();     
        }     
    }     
} 



使用lock方法的好处:
   1、ReentrantLock 拥有Synchronized相同的并发性和内存语义,此外还多了 锁投票,定时锁等候和中断锁等候
     线程A和B都要获取对象O的锁定,假设A获取了对象O锁,B将等待A释放对O的锁定,
     如果使用 synchronized ,如果A不释放,B将一直等下去,不能被中断
     如果使用ReentrantLock,如果A不释放,可以使B在等待了足够长的时间以后,中断等待,而干别的事情
 
    ReentrantLock获取锁定与三种方式:
    a)  lock(), 如果获取了锁立即返回,如果别的线程持有锁,当前线程则一直处于休眠状态,直到获取锁
    b) tryLock(), 如果获取了锁立即返回true,如果别的线程正持有锁,立即返回false;
    c)tryLock(long timeout,TimeUnit unit),   如果获取了锁定立即返回true,如果别的线程正持有锁,会等待参数给定的时间,在等待的过程中,如果获取了锁定,就返回true,如果等待超时,返回false;
    d) lockInterruptibly:如果获取了锁定立即返回,如果没有获取锁定,当前线程处于休眠状态,直到或者锁定,或者当前线程被别的线程中断
 
2、synchronized是在JVM层面上实现的,不但可以通过一些监控工具监控synchronized的锁定,而且在代码执行时出现异常,JVM会自动释放锁定,但是使用Lock则不行,lock是通过代码实现的,要保证锁定一定会被释放,就必须将unLock()放到finally{}中
 
3、在资源竞争不是很激烈的情况下,Synchronized的性能要优于ReetrantLock,但是在资源竞争很激烈的情况下,Synchronized的性能会下降几十倍,但是ReetrantLock的性能能维持常态;


原子性:
即不可被中断的操作属性,要么做完,要么不做;java的基本类型除了64位的double/long类型除外,其他的类型操作都是原子性的;
Java5提供了一些原子性变量类,对他操作时可以保证原子性的操作,AtomicInteger/AtomicLong/AtomicReference;优化代码时使用,一般情况下还是用synchronzied和显示同步锁lock来同步;


volatile:
被volatile修饰的域,那么它会告诉编译器,在编译此段域的时候,对域的读取和写入不要用一些缓存来优化,我直接读取此域的内存地址上的数据;如果多个任务同时访问同一个域,并且至少有一个是写入操作,那么这个域可以设置为volatile;


临界区:
多个线程同时访问方法内的部分代码,而不是全部代码,将这段代码抽离出来进行同步处理,这段代码叫临界区
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

帅气好男人_Jack

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值