📅  最后修改于: 2023-12-03 15:42:21.832000             🧑  作者: Mango
本题旨在考察程序员对于并发编程的掌握和理解,要求实现一个支持多个线程访问的计数器。
请实现一个名为 Counter
的计数器类,满足以下要求:
increment()
:将计数器加一。getCount()
:获取当前计数器的值。为了保证计数器的线程安全,我们可以使用 Java 内置的锁机制——synchronized
,在方法级别上添加同步锁,确保在同一时刻只能有一个线程访问计数器。
我们先来看一下基础实现的代码:
public class Counter {
private int count = 0;
public synchronized void increment() {
count++;
}
public synchronized int getCount() {
return count;
}
}
在 increment()
和 getCount()
方法的声明中,我们添加了 synchronized
关键字,这表示这两个方法是同步方法,多个线程在同时访问这两个方法时,只能有一个线程在执行,并且其他的线程将会在同步队列中等待,直到锁被释放。
在基础实现中,每次访问计数器都需要获得锁,这对于多线程高并发的应用来说,效率可能不太高。为了优化这种情况,我们可以采用另一种基于 CAS(Compare and Swap)机制的线程安全方式。
CAS 是目前比较流行的一种无锁算法,它将一个变量的当前值与期望值进行比较,如果相等,则执行特定操作,否则不做任何操作。这种方式可以避免线程的死锁和线程消耗过多资源的情况,适用于高并发、低冲突的应用场景。
下面是使用 CAS 机制的优化实现:
import java.util.concurrent.atomic.AtomicInteger;
public class Counter {
private AtomicInteger count = new AtomicInteger(0);
public void increment() {
count.incrementAndGet();
}
public int getCount() {
return count.get();
}
}
在这种情况下,我们不需要显式地使用锁机制来保证线程安全。我们使用了 AtomicInteger
类,它可以确保 incrementAndGet()
和 get()
方法的原子性。incrementAndGet()
方法会将当前值加 1,并返回新值,而 get()
方法会直接获取当前值。这两个方法都是原子性的,因此可以保证线程安全。
本题旨在考察程序员对于并发编程的掌握和理解,同时也是考察程序员解决问题的能力。在解决该问题时,我们可以采用 Java 内置的同步工具 synchronized
,也可以采用无锁算法 CAS
,具体的选择应该根据具体的业务要求而定。需要注意的是,为了保证代码的可读性和可维护性,在添加同步机制时应该尽可能地将同步逻辑独立出来,避免代码的臃肿,影响代码的可维护性。