其他分享
首页 > 其他分享> > JUC学习笔记——共享模型之管程

JUC学习笔记——共享模型之管程

作者:互联网

实际代码体现

// 针对counter,我们一个线程++,一个线程--各运行5000次
static int counter = 0;
public static void main(String[] args) throws InterruptedException {
    Thread t1 = new Thread(() -> {
        for (int i = 0; i < 5000; i++) {
            counter++;
        }
    }, "t1");
    Thread t2 = new Thread(() -> {
        for (int i = 0; i < 5000; i++) {
            counter--;
        }
    }, "t2");
    t1.start();
    t2.start();
    t1.join();
    t2.join();
    log.debug("{}",counter);
}


// 但结果却不是0,经常为-5000~5000之间的数

我们可以从底层代码分析问题:

/*i++底层代码*/ 

getstatic i // 获取静态变量i的值
iconst_1 	// 准备常量1
iadd 		// 自增
putstatic i // 将修改后的值存入静态变量i
    
/*i--底层代码*/ 
    
getstatic i // 获取静态变量i的值
iconst_1 	// 准备常量1
isub 		// 自减
putstatic i // 将修改后的值存入静态变量i

我们会发现他们的底层代码并不是一步实现,而是多步操作一同实现

但是如果是多线程,就会因为上下文切换的缘由导致部分步骤出现交杂(我们给出正数示例):

临界区和竞态条件

首先我们来简单介绍一下临界区:

针对临界区我们需要注意以下内容:

共享问题解决方案

这小节我们将会介绍共享问题解决方案

共享问题解决方案总述

synchronized简述

我们先来介绍synchronized的语法:

// 线程1, 线程2 都使用同一对象作为锁,这样一个运行,另一个处于blocked阻塞
synchronized(对象) 
{
    临界区
}

我们再给出相关代码示例:

// 我们创建一个room对象来作为锁,注意处理共享问题的线程需要绑定同一个锁

static int counter = 0;
static final Object room = new Object();
public static void main(String[] args) throws InterruptedException {
    Thread t1 = new Thread(() -> {
        for (int i = 0; i < 5000; i++) {
            synchronized (room) {
                counter++;
            }
        }
    }, "t1");
    Thread t2 = new Thread(() -> {
        for (int i = 0; i < 5000; i++) {
            synchronized (room) {
                counter--;
            }
        }
    }, "t2");
    t1.start();
    t2.start();
    t1.join();
    t2.join();
    log.debug("{}",counter);
}

我们做简单解释:

标签:代码,线程,变量,lock,synchronized,钥匙,开锁
来源: