在CPU多核缓存架构中,每个处理器都有一个单独的缓存,共享数据可能有多个副本:一个副本在主内存中,一个副本在请求它的每个处理器的本地缓存中。当数据的一个副本发生更改时,其他副本必须反映该更改。也就是说,CPU多核缓存架构要保证缓存一致性。
两种方式:
如果多个核上的线程在操作同一个缓存行(linux下缓存行有64个字节)中的不同变量数据,那么就会出现频繁的缓存失效,即使在代码层面看这两个线程操作的数据之间完全没有关系。这种不合理的资源竞争情况就是伪共享(FalseSharing)。
linux下查看缓存行大小:cat /proc/cpuinfo
避免伪共享方案:
public class FalseSharing {
public static void main(String[] args) throws InterruptedException {
Pointer pointer = new Pointer();
long start = System.currentTimeMillis();
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
for(int i = 0; i < 100000000; i++) {
pointer.x++;
}
}
});
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
for(int i = 0; i < 100000000; i++) {
pointer.y++;
}
}
});
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println(System.currentTimeMillis()-start);
}
static class Pointer {
volatile long x;
//缓存填充
long p1,p2,p3,p4,p5,p6,p7,p8;
volatile long y;
}
}
public class FalseSharing {
public static void main(String[] args) throws InterruptedException {
Pointer pointer = new Pointer();
long start = System.currentTimeMillis();
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
for(int i = 0; i < 100000000; i++) {
pointer.x++;
}
}
});
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
for(int i = 0; i < 100000000; i++) {
pointer.y++;
}
}
});
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println(System.currentTimeMillis()-start);
}
static class Pointer {
@Contended
volatile long x;
//缓存填充
//long p1,p2,p3,p4,p5,p6,p7,p8;
volatile long y;
}
}
juc下的队列大部分采用有界队列,有界队列通常采用数组实现。但是采用数组实现又会引发另外一个问题false sharing(伪共享)。Disruptor实现了队列的功能并且是一个有界队列,可以用于生产者-消费者模型。利用缓存行填充解决了伪共享的问题。
com.lmax
disruptor
3.4.2
EventFactory:创建事件(任务)的工厂类。ringBufferSize:容器的长度。
ThreadFactory:用于创建执行任务的线程。
ProductType:生产者类型:单生产者、多生产者。
WaitStrategy:等待策略。
@Data
public class OrderEvent {
private long value;
private String name;
}
public class OrderEventFactory implements EventFactory {
@Override
public OrderEvent newInstance() {
return new OrderEvent();
}
}
public class OrderEventProducer {
//存储事件的环形队列
private RingBuffer ringBuffer;
public OrderEventProducer(RingBuffer ringBuffer) {
this.ringBuffer = ringBuffer;
}
public void onData(long value, String name) {
//获取队列的下一个槽
long next = ringBuffer.next();
//获取消息
OrderEvent orderEvent = ringBuffer.get(next);
//写入数据
orderEvent.setValue(value);
orderEvent.setName(name);
System.out.println(String.format("生产着发送数据:value=%d name=%s", value, name));
ringBuffer.publish(next);
}
}
public class OrderEventHandler implements EventHandler {
@Override
public void onEvent(OrderEvent orderEvent, long l, boolean b) throws Exception {
System.out.println(String.format("消费者拿到数据:value=%d name=%s", orderEvent.getValue(), orderEvent.getName()));
}
}
单生产者单消费者模式
public class DisruptorDemo {
public static void main(String[] args) {
//创建Disruptor
Disruptor disruptor = new Disruptor<>(new OrderEventFactory(),
1024 * 1024,
Executors.defaultThreadFactory(),
ProducerType.SINGLE,
new YieldingWaitStrategy());
//设置消费者用于处理的事件
disruptor.handleEventsWith(new OrderEventHandler());
disruptor.start();
//创建队列容器
RingBuffer ringBuffer = disruptor.getRingBuffer();
//创建生产者
OrderEventProducer producer = new OrderEventProducer(ringBuffer);
for(int i = 0; i < 100; i++) {
producer.onData(i, "test"+i);
}
disruptor.shutdown();
}
}
单生产者多消费者模式
public class DisruptorDemo {
public static void main(String[] args) {
//创建Disruptor
Disruptor disruptor = new Disruptor<>(new OrderEventFactory(),
1024 * 1024,
Executors.defaultThreadFactory(),
ProducerType.SINGLE,
new YieldingWaitStrategy());
//设置消费者用于处理的事件
//disruptor.handleEventsWith(new OrderEventHandler());
//多消费者,重复消费
//disruptor.handleEventsWith(new OrderEventHandler(), new OrderEventHandler());
//设置多消费者,消费者要实现WorkHandler接口,一条消息只会被一个消费者消费
disruptor.handleEventsWithWorkerPool(new OrderEventHandler(), new OrderEventHandler());
disruptor.start();
//创建队列容器
RingBuffer ringBuffer = disruptor.getRingBuffer();
//创建生产者
OrderEventProducer producer = new OrderEventProducer(ringBuffer);
for(int i = 0; i < 100; i++) {
producer.onData(i, "test"+i);
}
disruptor.shutdown();
}
}
多生产者多消费者模式
public class DisruptorDemo {
public static void main(String[] args) throws InterruptedException {
//创建Disruptor
Disruptor disruptor = new Disruptor<>(new OrderEventFactory(),
1024 * 1024,
Executors.defaultThreadFactory(),
ProducerType.MULTI,
new YieldingWaitStrategy());
//设置消费者用于处理的事件
//disruptor.handleEventsWith(new OrderEventHandler());
//多消费者,重复消费
//disruptor.handleEventsWith(new OrderEventHandler(), new OrderEventHandler());
//设置多消费者,消费者要实现WorkHandler接口,一条消息只会被一个消费者消费
disruptor.handleEventsWithWorkerPool(new OrderEventHandler(), new OrderEventHandler());
disruptor.start();
//创建队列容器
RingBuffer ringBuffer = disruptor.getRingBuffer();
//创建生产者
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
OrderEventProducer producer = new OrderEventProducer(ringBuffer);
for(int i = 0; i < 100; i++) {
producer.onData(i, "test"+i);
}
}
});
//创建生产者
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
OrderEventProducer producer = new OrderEventProducer(ringBuffer);
for(int i = 0; i < 100; i++) {
producer.onData(i, "aaaa"+i);
}
}
});
t1.start();
t2.start();
t1.join();
t2.join();
disruptor.shutdown();
}
}