// 针对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的语法:
// 线程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,钥匙,开锁 来源:
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。