zzh

zzh

Pseudo-filling issue

Scenario

Rewriting different resources between multiple threads on a multi-core CPU.

Mechanism

Because CPUs often use caches to speed up variable reading, the MESI protocol can cause the corresponding cache lines on different CPUs to become invalid when threads on different CPUs modify their corresponding caches. When another CPU modifies a variable in that cache line (even if it is not the same variable), it will read from memory, causing the corresponding cache line of the original CPU to become invalid. This process repeats, causing the CPU to need to go through memory for every modification and reading of variables, unable to effectively utilize the cache, thereby slowing down the speed.

Code Implementation
  • False Sharing Occurs
public final class FalseSharing
        implements Runnable
{
    public final static int NUM_THREADS = 2; // change
    public final static long ITERATIONS = 500 * 1000 * 1000;
    private final int arrayIndex;

    private static VolatileLong[] longs = new VolatileLong[NUM_THREADS];
    static
    {
        for (int i = 0; i < longs.length; i++)
        {
            longs[i] = new VolatileLong();
        }
    }

    public FalseSharing(final int arrayIndex)
    {
        this.arrayIndex = arrayIndex;
    }

    public static void main(final String[] args) throws Exception
    {
        final long start = System.nanoTime();
        runTest();
        System.out.println("duration = " + (System.nanoTime() - start));
    }

    private static void runTest() throws InterruptedException
    {
        Thread[] threads = new Thread[NUM_THREADS];

        for (int i = 0; i < threads.length; i++)
        {
            threads[i] = new Thread(new FalseSharing(i));
        }

        for (Thread t : threads)
        {
            t.start();
        }

        for (Thread t : threads)
        {
            t.join();
        }
    }

    public void run()
    {
        long i = ITERATIONS + 1;
        while (0 != --i)
        {
            longs[arrayIndex].value = i;
        }
    }

    public final static class VolatileLong
    {
        public volatile long value = 0;
    }
}
  • False Sharing Does Not Occur
public final class FalseSharing
        implements Runnable
{
    public final static int NUM_THREADS = 2; // change
    public final static long ITERATIONS = 500 * 1000 * 1000;
    private final int arrayIndex;

    private static VolatileLong[] longs = new VolatileLong[NUM_THREADS];
    static
    {
        for (int i = 0; i < longs.length; i++)
        {
            longs[i] = new VolatileLong();
        }
    }

    public FalseSharing(final int arrayIndex)
    {
        this.arrayIndex = arrayIndex;
    }

    public static void main(final String[] args) throws Exception
    {
        final long start = System.nanoTime();
        runTest();
        System.out.println("duration = " + (System.nanoTime() - start));
    }

    private static void runTest() throws InterruptedException
    {
        Thread[] threads = new Thread[NUM_THREADS];

        for (int i = 0; i < threads.length; i++)
        {
            threads[i] = new Thread(new FalseSharing(i));
        }

        for (Thread t : threads)
        {
            t.start();
        }

        for (Thread t : threads)
        {
            t.join();
        }
    }

    public void run()
    {
        long i = ITERATIONS + 1;
        while (0 != --i)
        {
            longs[arrayIndex].value = i;
        }
    }

    @sun.misc.Contended
    public final static class VolatileLong
    {
        public volatile long value = 0;
    }
}

The JVM parameter -XX:-RestrictContended needs to be added.

Experimental Results
  • False Sharing Occurs

image

  • False Sharing Does Not Occur

image

Loading...
Ownership of this post data is guaranteed by blockchain and smart contracts to the creator alone.