双非本科准备秋招(17.2)—— 线程八锁

Synchronized

临界区:一段代码块内存在对共享资源的多线程读写操作,这段代码就是临界区。

竟态条件:多个线程在临界区执行,由于代码执行序列不同导致结果无法预测,称发生了竟态条件。

为了避免临界区竟态条件发生,可以使用如下方案:

  • 非阻塞式:原子变量。       
  • 阻塞式:synchronized,Lock;

 此次使用阻塞式解决方案:synchronized,俗称对象锁,这样,同一时刻只能有一个线程能持有对象锁,其他线程想获得这个对象锁就会被阻塞。

等价写法

   class test{h
        public synchronized void test(){

        }
    }
    //等价于
    class test {
        public void test() {
            synchronized (this){

            }
        }
    }
    class test{
        public synchronized static void test(){

        }
    }
    //等价于
    class test{
        public static void test(){
            synchronized (test.class){

            }
        }
    }

线程八锁

以上等价写法很重要。

线程八锁就是考察synchronized锁住了哪些对象。

情况1:

 @Slf4j(topic = "c.Number")
 class Number{
     public synchronized void a() {
         log.debug("1");
     }
     public synchronized void b() {
         log.debug("2");
     }
 }
 public static void main(String[] args) {
     Number n1 = new Number();
     new Thread(()->{ n1.a(); }).start();
     new Thread(()->{ n1.b(); }).start();
 }

两个线程一起竞争锁,有可能是12,也有可能是21

情况2:

@Slf4j(topic = "c.Number")
class Number{
    public synchronized void a() {
        sleep(1);
        log.debug("1");
    }
    public synchronized void b() {
        log.debug("2");
    }
}
public static void main(String[] args) {
    Number n1 = new Number();
    new Thread(()->{ n1.a(); }).start();
    new Thread(()->{ n1.b(); }).start();
}

两个线程一起竞争锁,所以可能是sleep1,然后2。或者2,或sleep1,然后1,2。

情况3:

@Slf4j(topic = "c.Number")
class Number{
    public synchronized void a() {
        sleep(1);
        log.debug("1");
    }
    public synchronized void b() {
        log.debug("2");
    }
    public void c() {
        log.debug("3");
    }
}
public static void main(String[] args) {
    Number n1 = new Number();
    new Thread(()->{ n1.a(); }).start();
    new Thread(()->{ n1.b(); }).start();
    new Thread(()->{ n1.c(); }).start();
}

c没加锁,a、b竞争,可能是sleep1,1、2,或者2,sleep1,1,3可以任意,但肯定在sleep之前。

所以可能是:

①3,sleep1、1,2

②3,2,sleep1,1

③2,3,sleep1,1

情况4:

两个不同的对象,锁是不同的锁,所以没有竞争,一定是2,然后sleep1,1。

@Slf4j(topic = "c.Number")
class Number{
    public synchronized void a() {
        sleep(1);
        log.debug("1");
    }
    public synchronized void b() {
        log.debug("2");
    }
}
public static void main(String[] args) {
    Number n1 = new Number();
    Number n2 = new Number();
    new Thread(()->{ n1.a(); }).start();
    new Thread(()->{ n2.b(); }).start();
}

情况5:

这就用到等价写法的知识了,可以看到这两个方法的锁对象不同,所以没有竞争关系,一定是2,然后sleep1,1。

@Slf4j(topic = "c.Number")
class Number{
    public static synchronized void a() {
        sleep(1);
        log.debug("1");
    }
    public synchronized void b() {
        log.debug("2");
    }
}
public static void main(String[] args) {
    Number n1 = new Number();
    new Thread(()->{ n1.a(); }).start();
    new Thread(()->{ n1.b(); }).start();
}

情况6:

两个锁的都是类对象,可能是sleep1,1,然后2,或者2,然后sleep1,1。

@Slf4j(topic = "c.Number")
class Number{
    public static synchronized void a() {
        sleep(1);
        log.debug("1");
    }
    public static synchronized void b() {
        log.debug("2");
    }
}
public static void main(String[] args) {
    Number n1 = new Number();
    new Thread(()->{ n1.a(); }).start();
    new Thread(()->{ n1.b(); }).start();
}

情况7:

两个对象,一个是锁住类对象,一个锁住实例对象,所以没有竞争,总是2然后sleep1,1。

@Slf4j(topic = "c.Number")
class Number{
    public static synchronized void a() {
        sleep(1);
        log.debug("1");
    }
    public synchronized void b() {
        log.debug("2");
    }
}
public static void main(String[] args) {
    Number n1 = new Number();
    Number n2 = new Number();
    new Thread(()->{ n1.a(); }).start();
    new Thread(()->{ n2.b(); }).start();
}

情况8:

虽然对象不同,但是锁的都是类对象,所以有竞争。

可能是sleep1,1,然后2;或者2,然后sleep1,然后1。

@Slf4j(topic = "c.Number")
class Number{
    public static synchronized void a() {
        sleep(1);
        log.debug("1");
    }
    public static synchronized void b() {
        log.debug("2");
    }
}
public static void main(String[] args) {
    Number n1 = new Number();
    Number n2 = new Number();
    new Thread(()->{ n1.a(); }).start();
    new Thread(()->{ n2.b(); }).start();
}
  • 10
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值