Java并发编程——共享资源竞争问题

案例分析

创建两个线程 t1 、t2 ,t1 线程负责变量 count 自增 5000 次,t2 线程负责变量 count 自减 5000 次

public class AddAndSub {
	static int count = 0;

	public static void main(String[] args) throws InterruptedException {
		Thread t1 = new Thread() {
			@Override
			public void run() {
				for (int i = 0; i < 5000; i++) {
					count++;
				}
			}
		};

		Thread t2 = new Thread() {
			@Override
			public void run() {
				for (int i = 0; i < 5000; i++) {
					count--;
				}
			}
		};

		t1.start();
		t2.start();
		t1.join();
		t2.join();
		System.out.println(count);
	}
}

由于线程执行的顺序不受控制,可能会发生如下情况:

假设此时 count 值为 0 ,t1 线程读取到 count 的值,进行自增后变成 1 ,还没来得及写入 count ,t2 线程就读取了 count 原来的值 0 ,进行自减后,将 -1 写入 count ,然后 t1 线程将刚刚自增得到的结果 1 写入 count ,最终导致了分别进行一次自增自减后,count 的值从 0 变成了 1


概念介绍

临界资源

一次仅允许一个进程使用的共享资源,如物理设备中的打印机、输入机和进程之间共享的变量、数据

临界区(Critical Section)

每个进程中访问临界资源的代码段,如上述案例中的 count++

竟态条件(Race Condition)

两个或者多个进程竞争使用临界资源,这些进程可能因为执行先后顺序的不受控制而出现问题,如上述案例中的 t1 和 t2 线程执行顺序不受控制,导致结果错误


synchronized 实现互斥

static Object lock = new Object();

synchronized (lock) {
	count++;
}

synchronized (lock) {
	count--;
}

使用 synchronized 关键字对 lock 对象加锁,当其中一个线程对 count 进行自增或自减操作时,另外的线程由于获取不到 lock 锁,被阻塞,保证了临界区内代码的原子性


封装共享资源

public class AddAndSubOptimize {
	public static void main(String[] args) throws InterruptedException {
		Resource resource = new Resource();
		Thread t1 = new Thread() {
			@Override
			public void run() {
				for (int i = 0; i < 5000; i++) {
					resource.increment();
				}
			}
		};

		Thread t2 = new Thread() {
			@Override
			public void run() {
				for (int i = 0; i < 5000; i++) {
					resource.decrement();
				}
			}
		};

		t1.start();
		t2.start();
		t1.join();
		t2.join();
		System.out.println(resource.getCount());
	}
}

class Resource {
	private int count = 0;

	public void increment() {
		synchronized (this) {
			count++;
		}
	}

	public void decrement() {
		synchronized (this) {
			count--;
		}
	}

	public int getCount() {
		synchronized (this) {
			return count;
		}
	}
}

通过 Resource 类封装了共享资源(变量)count ,对变量操作的互斥逻辑在类的内部实现,外部只需要调用相应的方法即可

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值