【问题标题】:Thread safe field, avoid read write collisions线程安全字段,避免读写冲突
【发布时间】:2015-11-22 11:18:05
【问题描述】:

我正在尝试编写 synccollection 我因读/写问题而崩溃了

我在每个线程中运行这段代码

public void run() {
    for (int j = 0; j < threadElemAmount; j++) {
        list.remove((int) (list.size() - 1));
    }
}

方法内部的代码大小和运行

public T remove(int index){
    lock.lock();
    if (index >= size || index < 0)
        throw new IndexOutOfBoundsException("illegal index value, index = " + index + " size = " + size);
    T removedElement = (T) data[index];
    int movedElementsAmount = size - index - 1;
    //проверить кол-во перемещаемых элементов справа
    if (movedElementsAmount > 0) {
        System.arraycopy(data, index + 1, data, index, movedElementsAmount);
     }
     // очищаем последний
     data[--size] = null;
     lock.unlock();
     return removedElement;    
}

和大小

public int size() {
    lock.lock();
    int result = size;
    lock.unlock();
    return result; 
}

我不能使用同步关键字这是特殊情况的一部分,只是锁定,几乎相同。 因此,最薄弱的地方是 list.size() 调用和 list.remove() 调用之间的 ulocked 空间。如何避免读/写问题?

【问题讨论】:

    标签: java multithreading thread-safety read-write


    【解决方案1】:

    你需要为pop()写一个同步函数。

    remove(index) 不能很好地替代线程安全的 pop 函数。

    另外,您应该将代码更改为:

    lock.lock()
    try {
    .
    .
    .
    } finally {
        lock.unlock();
    }
    

    为了使其异常安全。

    最后但同样重要的是,size() 不需要同步。只需返回大小,因为它是只读操作。您可能希望将 size 参数设置为 volatile,但这里并不是特别需要。

    【讨论】:

    • pop 可以指删除第一个或最后一个元素,具体取决于实现Deque 定义了一个removeLast()
    • 我不想只用 pop 或 remove last 连接,如果我想每次删除元素 list.size()- 3 或者其他综合案例我应该怎么做跨度>
    • 实现removrFromEnd(int index)。 0 表示最后一个元素,1 表示最后一个元素,等等。
    • 你不明白与端元素的连接是不好的。只需要连接索引
    • 如果我想使用 removeFromeEnd(list.size() - 2) 怎么办:这会因同样的读写问题而崩溃。绝对糟糕的解决方案
    【解决方案2】:

    您的选择是;

    • 公开锁,以便在两个选项期间都可以保持它。
    • 与可见的锁一起​​使用同步。
    • 添加 removeLast() 操作。
    • 添加一个 drainTo() 操作。
    • 使用一个内置的线程安全集合,它已经这样做了。

    您似乎想要排空 N 个对象,所以最后一个选项可能是最好的。

    【讨论】:

    • 如果我使用其他情况,而不是最后删除,我可以避免为每种情况编写特殊方法吗?
    • @jenius 是的,您可以实现自己的 drainTo() 或直接删除多个元素的 drain()。
    猜你喜欢
    • 1970-01-01
    • 2019-02-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多