当前位置: 代码迷 >> 综合 >> 并发编程——按顺序打印-AtomicInteger类
  详细解决方案

并发编程——按顺序打印-AtomicInteger类

热度:70   发布时间:2024-02-13 02:18:10.0

一、AtomicInteger类:

高并发的情况下,i++无法保证原子性,往往会出现问题,所以引入AtomicInteger类。

class Foo {private AtomicInteger firstJobDone = new AtomicInteger(0);private AtomicInteger secondJobDone = new AtomicInteger(0);public Foo() {}public void first(Runnable printFirst) throws InterruptedException {// printFirst.run() outputs "first".printFirst.run();// mark the first job as done, by increasing its count.firstJobDone.incrementAndGet();}public void second(Runnable printSecond) throws InterruptedException {while (firstJobDone.get() != 1) {// waiting for the first job to be done.}// printSecond.run() outputs "second".printSecond.run();// mark the second as done, by increasing its count.secondJobDone.incrementAndGet();}public void third(Runnable printThird) throws InterruptedException {while (secondJobDone.get() != 1) {// waiting for the second job to be done.}// printThird.run() outputs "third".printThird.run();}
}

 

二、Semaphore类:

Semaphore 是一个计数信号量。常用于限制可以同时访问某些资源的线程数量,例如通过 Semaphore 限流。

Semaphore中包含初始化时固定个数的许可,在进行操作的时候:

  • 需要先acquire获取到许可,才可以继续执行任务,如果获取失败,则进入阻塞;
  • 处理完成之后需要release释放许可。

acquire与release之间的关系:在实现中不包含真正的许可对象,并且Semaphore也不会将许可与线程关联起来,因此在一个线程中获得的许可可以在另一个线程中释放。可以将acquire操作视为是消费一个许可,而release操作是创建一个许可,Semaphore并不受限于它在创建时的初始许可数量。也就是说acquire与release并没有强制的一对一关系,release一次就相当于新增一个许可,许可的数量可能会由于没有与acquire操作一对一而导致超出初始化时设置的许可个数。

例如:实现交替打印指定次数foobar

  • 首先限制最多一个线程拿到信号量foo,限制没有线程可以拿到信号bar
  • 当bar()先被线程调用时候,bar.acquire会被阻塞
  • 当foo()先被线程调用时候,foo.acquire获得了许可,可以继续执行,然后bar.release创建一个许可。
  • 这时候如果执行bar()则可以正常调用,但如果有一个线程进入了foo(),foo.acquire会被阻塞。
class FooBar {private int n;public FooBar(int n) {this.n = n;}Semaphore foo = new Semaphore(1); // 限制了最多一个线程可以拿到foo信号量Semaphore bar = new Semaphore(0); // 限制没有线程可以拿到bar信号量public void foo(Runnable printFoo) throws InterruptedException {for (int i = 0; i < n; i++) {foo.acquire();printFoo.run();bar.release();}}public void bar(Runnable printBar) throws InterruptedException {for (int i = 0; i < n; i++) {bar.acquire();printBar.run();foo.release();}}
}

 

 

  相关解决方案