关于线程的同步

线程的同步

描述一下一个线程从始至终的运行状态
(1)一个线程新建了,调用start()之后就进入就绪状态,等待cpu来调用他
(2)CPU调用到他了,如果他需要的资源足够,他就进入运行状态;在他运行的时候,随时有可能被CPU撤掉,收回他的资源,再次进入就绪状态;
在运行时,还有可能自己调用wait()方法或sleep()等,进入阻塞状态,这时他得释放掉自己占用的资源,等待sleep时间/被notify
如果代码都运行完毕就进入死亡状态了

判断是否存在线程安全的问题:
(1)是否有多个线程
(2)是否有多个线程操作同一个共享数据
(3)是否有多条语句与共享变量有关

1、同步代码块
synchronized(锁对象){
      需要同步的代码
}

锁对象:
语法上,任意类型的对象都可以
几个相关的线程必须公用一把锁,这多个线程共享这一把锁
注意一次锁一个单元的任务,例如卖一张票的这个过程

如果是通过实现Runnable创建的线程的话,那就可以直接用this了,因为是同一个对象,所以锁对象也可以使用this了,共享的数据也不用必须用static修饰了,因为他们公用了一个线程代理

2、同步方法    直接对方法进行修饰
这样的话锁的就是整个方法了

非静态方法时,锁对象是this
静态方法时,锁对象是类名.class

当在对象上任意的synchronized方法的时候,对象都会被加锁,这个时候该对象的其他synchronize方法只有等到前一个方法调用完毕之后才能被调用。对于某个特定的对象来说,其所有的synchronize方法共享同一个锁,这样可以


关于线程的通信

设计到的方法
wait:等待
notify/notigyAll:通知
这些方法必须由锁对象来调用,这个锁对象是多个线程所共享的;
wait会让当前线程进入阻塞状态
notify会使当前线程从阻塞状态变回就绪状态


还有一种显示锁Lock
synchronized是JVM层面提供的锁,而Lock是Java语言层面jdk为我们提供的锁;这些锁都在java.util.concurrent包中
lock的加锁和释放都全部由我们控制,通常释放锁要在finally中实现
synchronized只有一个状态条件,就是每个对象只有一个监视器;如果需要多个Condition的组合,那么synchronized是无法满足的,而Lock则提供了多条件的互斥,更灵活

Lock和Condition

Lock lock = new ReentrantLock();//显示锁对象
lock.lock();//锁上
lock.unlock();//开锁

通信时
如果使用Lock锁,那么线程通信需要使用Condition解决
条件.await()//某种条件,等待
条件.signal()//某种条件,唤醒
Lock lock = new ReentrantLock();
Condition full = lock.newCondition();
Condition empty = lock.newCondition();
lock.lock();

full.await();
empty.signal();//signalAll()

lock.unlock();

empty.await();
full.singal();

关于单例模式需要注意的
懒汉式的时候:
public static Lazy getInstance(){
       if(instance ==null){
          synchronized(Lazy.class){
            if(instance==null){
                 instance = new Lazy();
            }    
          }    
       }
 return instance;
}
多了一层的判断,时为了避免每次判断都得执行同步代码块消耗时间








  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值