我可以使用ArrayList实例同步代码块吗?

时间:2016-01-27 16:33:30

标签: java

我知道有一种方法可以在Java中同步变量。那就是使用锁。

public class MsLunch {
    private ArrayList<ClientHandler> clients = new ArrayList<ClientHandler>();

    private Object lock1 = new Object();

    public void inc1() {
        synchronized(lock1) {
            //maybe add something into the array list
        }
    }
}

我很好奇我们是否可以按照以下方式进行操作?如果是,任何参考?

public class MsLunch {
    private ArrayList<ClientHandler> clients = new ArrayList<ClientHandler>();

    public void inc1() {
        synchronized (clients) {
            //maybe add something into the array list
        }
    }
}

3 个答案:

答案 0 :(得分:0)

如果使用clients同步代码块,则没有问题。您可以使用任何对象引用来同步代码块。只需确保不会在多个线程的同一实例中重新初始化此对象。

如果你需要一个可以通过线程访问的容器,我建议先查看QueueMap,因为通常他们可以解决很多用例。如果您只需要List,我建议使用Collections#synchronized(yourList),并作为最后一个资源CopyOnWriteArrayList。尽管如此,这些方法中的任何一种都比自己同步这些资源更好。

答案 1 :(得分:0)

是的,你可以,但你不应该...... Java在java.util.concurrent package中使用并发List实用程序。使用CopyOnWriteArrayList 而不是使用synchronize关键字性能更好地使用并发实用程序。这将使您免于处理锁的麻烦 在你的代码中。

答案 2 :(得分:0)

  

我对我们是否可以按照以下方式进行操作感到好奇?

是的,你可以。

  

如果是,可以参考吗?

您可以在任何Object上执行同步。因为ArrayListObject,所以你可以这样做。

你应该将clients声明为final变量,因为不同的线程可能会锁定不同的对象,即使在同一个对象上运行也是如此。

此外,您可以使用java.util.concurrent.locks.Lock和/或java.util.concurrent.locks.ReadWriteLock代替synchronized阻止,或只使用符合您需求的java.util.concurrent.CopyOnWriteArrayList

我做了一个简单的性能测试:

import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

public class ConcurrentReadWriteListTest {

    public static void main(String[] args) throws InterruptedException {
        final int iterations = 10;
        final long durationMillis = 5000;
        System.out.println("WarmUp :");
        System.out.println("\n************* SynchronizedArrayList ************");
        testSynchronizedArrayList(5, 1000);
        System.out.println("\n************* CopyOnWriteArrayList *************");
        testCopyOnWriteArrayList(5, 1000);
        System.out.println("\n********** ArrayListWithReadWriteLock **********");
        testArrayListWithReadWriteLock(5, 1000);
        System.out.println("\n\nStart Test :");
        System.out.println("\n************* SynchronizedArrayList ************");
        testSynchronizedArrayList(iterations, durationMillis);
        System.out.println("\n************* CopyOnWriteArrayList *************");
        testCopyOnWriteArrayList(iterations, durationMillis);
        System.out.println("\n********** ArrayListWithReadWriteLock **********");
        testArrayListWithReadWriteLock(iterations, durationMillis);
    }

    static void testSynchronizedArrayList(int iterations, long durationMillis) {
        final List<TestObject> list = Collections.synchronizedList(new ArrayList<>());
        final AtomicInteger writes = new AtomicInteger();
        final AtomicInteger reads = new AtomicInteger();
        final Runnable w = () -> {
            while (notInterrupted()) {
                list.add(new TestObject());
                writes.getAndIncrement();
            }
        };
        final Runnable r = () -> {
            while (notInterrupted()) {
                if (!list.isEmpty()) {
                    list.get(ThreadLocalRandom.current().nextInt(list.size())).map.size();
                    reads.getAndIncrement();
                }
            }
        };
        beginTest(iterations, durationMillis, list, writes, reads, w, r);
    }

    static void testCopyOnWriteArrayList(int iterations, long durationMillis) {
        final List<TestObject> list = new CopyOnWriteArrayList<>();
        final AtomicInteger writes = new AtomicInteger();
        final AtomicInteger reads = new AtomicInteger();
        final Runnable w = () -> {
            while (notInterrupted()) {
                list.add(new TestObject());
                writes.getAndIncrement();
            }
        };
        final Runnable r = () -> {
            while (notInterrupted()) {
                if (!list.isEmpty()) {
                    list.get(ThreadLocalRandom.current().nextInt(list.size())).map.size();
                    reads.getAndIncrement();
                }
            }
        };
        beginTest(iterations, durationMillis, list, writes, reads, w, r);
    }

    static void testArrayListWithReadWriteLock(int iterations, long durationMillis) {
        final List<TestObject> list = new ArrayList<>();
        final ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
        final AtomicInteger writes = new AtomicInteger();
        final AtomicInteger reads = new AtomicInteger();
        final Runnable w = () -> {
            while (notInterrupted()) {
                readWriteLock.writeLock().lock();
                list.add(new TestObject());
                readWriteLock.writeLock().unlock();
                writes.getAndIncrement();
            }
        };
        final Runnable r = () -> {
            while (notInterrupted()) {
                readWriteLock.readLock().lock();
                if (!list.isEmpty()) {
                    list.get(ThreadLocalRandom.current().nextInt(list.size())).map.size();
                    reads.getAndIncrement();
                }
                readWriteLock.readLock().unlock();
            }
        };
        beginTest(iterations, durationMillis, list, writes, reads, w, r);
    }

    static void beginTest(int iterations, long durationMillis,
                          List<TestObject> list,
                          AtomicInteger writes, AtomicInteger reads,
                          Runnable w, Runnable r) {
        double totalWPS = 0, totalRPS = 0;
        for (int i = 0; i < iterations; i++) {
            Thread writer = new Thread(w);
            Thread reader = new Thread(r);
            writer.start();
            reader.start();
            sleep(durationMillis);
            writer.interrupt();
            reader.interrupt();
            double wps = writes.get() * 1.0 / durationMillis * 1000;
            double rps = reads.get() * 1.0 / durationMillis * 1000;
            totalWPS += wps;
            totalRPS += rps;
            System.out.printf("round(%d) : %.2f w/s, %.2f r/s%n", i + 1, wps, rps);
            list.clear();
            writes.set(0);
            reads.set(0);
        }
        System.out.printf("overall : %.2f w/s, %.2f r/s%n", totalWPS / iterations, totalRPS / iterations);
    }

    static boolean notInterrupted() {
        return !Thread.currentThread().isInterrupted();
    }

    static void sleep(long timeout) {
        try {
            Thread.sleep(timeout);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    static final class TestObject {

        int i;
        long l;
        float f;
        double d;
        Map<Long, String> map = new HashMap<>();

        TestObject() {
            map.put(1L, "a");
            map.put(2L, "b");
            map.put(3L, "c");
            map.put(4L, "d");
        }

    }

}

结果如下:

WarmUp :

************* SynchronizedArrayList ************
round(1) : 417859.00 w/s, 361950.00 r/s
round(2) : 845857.00 w/s, 796326.00 r/s
round(3) : 1444301.00 w/s, 1731925.00 r/s
round(4) : 1170101.00 w/s, 954809.00 r/s
round(5) : 1373893.00 w/s, 1343517.00 r/s
overall : 1050402.20 w/s, 1037705.40 r/s

************* CopyOnWriteArrayList *************
round(1) : 52490.00 w/s, 12505323.00 r/s
round(2) : 54170.00 w/s, 12963819.00 r/s
round(3) : 55552.00 w/s, 12723022.00 r/s
round(4) : 56634.00 w/s, 12963812.00 r/s
round(5) : 57261.00 w/s, 12859154.00 r/s
overall : 55221.40 w/s, 12803026.00 r/s

********** ArrayListWithReadWriteLock **********
round(1) : 1526100.00 w/s, 47806.00 r/s
round(2) : 2028127.00 w/s, 97690.00 r/s
round(3) : 2277951.00 w/s, 129597.00 r/s
round(4) : 2065762.00 w/s, 178288.00 r/s
round(5) : 1815661.00 w/s, 200642.00 r/s
overall : 1942720.20 w/s, 130804.60 r/s


Start Test :

************* SynchronizedArrayList ************
round(1) : 766045.40 w/s, 670402.20 r/s
round(2) : 943151.00 w/s, 596922.60 r/s
round(3) : 799154.60 w/s, 603495.60 r/s
round(4) : 799162.40 w/s, 633526.40 r/s
round(5) : 799159.80 w/s, 595249.40 r/s
round(6) : 798720.00 w/s, 526994.40 r/s
round(7) : 959635.00 w/s, 692030.20 r/s
round(8) : 959631.60 w/s, 651675.00 r/s
round(9) : 959632.40 w/s, 652545.80 r/s
round(10) : 959632.40 w/s, 689399.60 r/s
overall : 874392.46 w/s, 631224.12 r/s

************* CopyOnWriteArrayList *************
round(1) : 23536.60 w/s, 13772252.60 r/s
round(2) : 24099.40 w/s, 13332508.00 r/s
round(3) : 24754.80 w/s, 12908797.20 r/s
round(4) : 24895.80 w/s, 12503731.20 r/s
round(5) : 24799.40 w/s, 12386501.60 r/s
round(6) : 24966.20 w/s, 12297215.40 r/s
round(7) : 24769.00 w/s, 12245010.20 r/s
round(8) : 24958.80 w/s, 12399174.00 r/s
round(9) : 24748.40 w/s, 12353819.80 r/s
round(10) : 24942.80 w/s, 12400986.80 r/s
overall : 24647.12 w/s, 12659999.68 r/s

********** ArrayListWithReadWriteLock **********
round(1) : 816296.80 w/s, 67670.40 r/s
round(2) : 872701.20 w/s, 81845.20 r/s
round(3) : 936945.20 w/s, 72189.40 r/s
round(4) : 936311.00 w/s, 80164.40 r/s
round(5) : 934575.00 w/s, 80447.80 r/s
round(6) : 932832.60 w/s, 95923.00 r/s
round(7) : 935632.20 w/s, 85815.00 r/s
round(8) : 935526.20 w/s, 85754.40 r/s
round(9) : 930819.20 w/s, 92297.60 r/s
round(10) : 934331.20 w/s, 94485.60 r/s
overall : 916597.06 w/s, 83659.28 r/s
  • JVM:Java HotSpot(TM)64位服务器VM(版本25.72-b15,混合模式)
  • 操作系统:Win 10 Pro 64位
  • CPU:Intel Core i7-4700HQ @ 2.40GHz 2.40GHz

所以,如果你想要更多更好的

  • 并发阅读,请使用CopyOnWriteArrayList
  • 并发写入,将ArrayListReadWriteLock一起使用

如果你想要介于两者之间,请使用synchronized阻止。