2016-02-24 6 views
4

Когда я прочитал mechnism «Ложное разделение» в Java, я нашел следующий код в java.util.concurrent.Exchanger.SlotПочему java's Exchanger.Slot кэширует строки так, как это?

/** 
* A Slot is an AtomicReference with heuristic padding to lessen 
* cache effects of this heavily CAS'ed location. While the 
* padding adds noticeable space, all slots are created only on 
* demand, and there will be more than one of them only when it 
* would improve throughput more than enough to outweigh using 
* extra space. 
*/ 
private static final class Slot extends AtomicReference<Object> { 
    // Improve likelihood of isolation on <= 64 byte cache lines 
    long q0, q1, q2, q3, q4, q5, q6, q7, q8, q9, qa, qb, qc, qd, qe; 
} 

Это strange.Why число долго 15 (q0 - qe), Таким образом, я могу рассчитать размер объекта:
15 * 8 (длинный) + 8 (длинное значение родителя) + (указатель заголовка объекта на 64 бит jvm) = 144 байт.
или:
15 * 8 (длинный) + 8 (длинное значение родителя) + (указатель заголовка объекта при 32 бит jvm) = 136 байт.
Как я в Disruptor's implemention: прочитанные

public long p1, p2, p3, p4, p5, p6, p7; // cache line padding 

private volatile long cursor = INITIAL_CURSOR_VALUE; 

public long p8, p9, p10, p11, p12, p13, p14; // cache line padding 

размер должен быть 7 * 8 + 8 + 7 * 8 + 8 (объект головки opinter'size при 32 бита JVM) = 128 = 64 * 2.
As размер строки кеша по умолчанию для большинства процессоров составляет 64 байта, поэтому импликатор discruptor может избежать «Ложного обмена».
Так что мой вопрос - это количество заполненных длинными в классе java.util.concurrent.Exchanger.Slot верное или неправильное?

ответ

0

Прокладка в java.util.concurrent.Exchanger.Slot играет в нее безопасно. Он добавляет дополнительную прокладку, а с другой стороны, разрыватель добавляет достаточно.

Кроме того, подрывный подход может завершиться неудачно, если JVM переупорядочивает поля, а размер строки кеша - 128 бит. Самый безопасный подход к отдельным полям по наследству:

class MemoryFieldAddress { 
    private long address; 

    public final long getAddress() { 
     return address; 
    } 

    protected final void setAddress(final long address) { 
     this.address = address; 
    } 
} 

class MemoryAddressPad1 extends MemoryFieldAddress { 
    long p1_1, p1_2, p1_3, p1_4, p1_5, p1_6, p1_7, p1_8, p1_9, p1_10, p1_11, p1_12, p1_13, p1_14, p1_15, p1_16, p1_17; 
} 

class MemoryFieldBytes extends MemoryAddressPad1 { 
    private long bytes; 

    public final long getBytes() { 
     return bytes; 
    } 

    protected final void setBytes(final long bytes) { 
     this.bytes = bytes; 
    } 
} 

class MemoryAddressPad2 extends MemoryFieldBytes { 
    long p2_1, p2_2, p2_3, p2_4, p2_5, p2_6, p2_7, p2_8, p2_9, p2_10, p2_11, p2_12, p2_13, p2_14, p2_15, p2_16, p2_17; 
} 

// Finally the full implimentation 
public class Memory extends MemoryAddressPad2 {} 

Если вы хотите, вы можете рассчитывать конечные поля и редко обновляются поля в направлении заполнения.