java并发-线程安全与共享资源(4)

来源:互联网 发布:随身wifi网络链接异常 编辑:程序博客网 时间:2024/05/22 17:42

允许多个线程同时运行的代码就是线程安全的代码。下面讲的是需要注意的线程安全的几种情况:

1.局部原始变量

局部原始变量都是线程安全的,因为这种变量在每个线程都有一个副本。例如:对于局部变量int x=0;那么每个线程在栈中都会有一个自己的x。

package com.concurenny.chapter.four;/** * 创建者:Mr lebron 创建时间:2017年11月16日 下午7:05:12 */public class LocalVariableDemo {public static void main(String[] args) {new Thread(() -> {// 获取原始类型的局部变量,并修改.原始类型的变量不会改变。// 因为每个线程执行getVariable()都会保存一个x副本,即每个线程拥有一个自己的x变量。// 所以线程安全int y = getVariable() + 1;System.out.println("modified:" + y + "  origin:" + getVariable());}).start();new Thread(() -> {// 获取原始类型的局部变量,并修改.原始类型的变量不会改变。// 因为每个线程执行getVariable()都会保存一个x副本,即每个线程拥有一个自己的x变量。// 所以线程安全int z = getVariable() + 1;System.out.println("modified:" + z + "  origin:" + getVariable());}).start();}public static int getVariable() {int x = 100;return x;}}

局部的对象引用

这种很容易出现线程安全问题。因为一个线程创建的对象引用可能赋值给另外一个线程。


package com.concurenny.chapter.four;/** * 创建者:Mr lebron 创建时间:2017年11月16日 下午7:16:49 */public class LocalRefererDemo {public static void main(String[] args) {new Thread(() -> {// 获取一个局部Counter变量的引用,并赋值=100final Counter counter = escapeReferer();counter.setCount(100);// 另外一个线程对该counter引用修改new Thread(() -> {counter.setCount(101);}).start();try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}// 局部变量counter被另外一个线程修改了,所以这不是线程安全的局部引用变量System.out.println("100 == " + counter.getCount() + "?");}).start();}public static Counter escapeReferer() {Counter counter = new Counter();return counter;}static class Counter {private int count = 0;public int getCount() {return count;}public void setCount(int count) {this.count = count;}}}

对象成员

一个对象的成员属于多个线程的共享数据,必然不是线程安全的。

package com.concurenny.chapter.four;/** * 创建者:Mr lebron 创建时间:2017年11月16日 下午7:36:26 */public class ObjectMemberDemo {// 共享变量static Worker worker = new Worker();public static void main(String[] args) {// 开启一个线程读取共享变量的值new Thread(() -> {try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("salary:" + worker.getSalary());}).start();// 修改共享变量的值,开启30个线程,每个线程对salary+1,那么最后应该得到1000030?结果是如此吗?,多运行几次就知道了for (int i = 0; i < 30; i++) {new Thread(() -> {worker.setSalary(worker.getSalary() + 1);}).start();}}static class Worker {private double salary = 1_000_000;public double getSalary() {return salary;}public void setSalary(double salary) {this.salary = salary;}}}


原创粉丝点击