在典型的存储环境中,线程安全可能意味着什么?[关闭]

What might thread-safety entail in a typical storage environment? [closed]

提问人:kesarling He-Him 提问时间:11/13/2023 更新时间:11/13/2023 访问量:64

问:


想改进这个问题吗?通过编辑这篇文章添加详细信息并澄清问题。

6天前关闭。

我正在学习java中的多线程。我编写了一个简单的通用存储类,它始终按升序存储对象。我现在想让它线程安全。一种方法(也可能是最简单的方法)是:

// LinkedList implementation of a typical BST
class MyStorage<T> { // implements a comparable and some other interfaces not required by the MRE
    private BSTreeNode rootNode;

    // in case of duplicates, the occurrence property of the BSTreeNode is utilized
    public synchronized boolean add(T);
    public synchronized boolean delete(T);
    public synchronized boolean search(T);
}

存储电流:1,2,3,4,5,6,7,9

但是,我觉得这不是一个好主意,因为一个线程擦除 6 个线程而另一个线程添加 8 是完全可以接受的,无论它们以什么顺序调用或中断,存储都会给出正确的结果。我觉得需要的是专门对同一值执行 2 个不同的操作。

这就是我目前在想的:

// same sync block for every(or just add/delete?) function
public boolean add(T value) {
    synchronized(/*some sort of mutex on the value object instead of on this*/) {

    }
}

我将如何实现这一目标?

Java 同步线程 同步

评论

1赞 experiment unit 1998X 11/13/2023
如果您打算只同步其上的块以执行添加/删除功能,则可以创建一个随机对象作为类变量。但是,这通常是可重入锁,您可以尝试锁定/解锁它,而不是使用同步块
1赞 kesarling He-Him 11/13/2023
@experimentunit1998X,这和同步方法基本上不是一回事吗?
1赞 Sweeper 11/13/2023
“一个线程擦除 6 个线程,另一个线程添加 8 个线程是完全可以接受的,无论它们以什么顺序调用”是的,您当前的实现允许这样做。当前实现不允许同时执行其中两个操作。(请注意,我并不是说没有更细粒度的方法可以做到这一点,只是你想要的已经完成了)
1赞 kesarling He-Him 11/13/2023
@Sweeper,我想要的是他们允许,但不允许,这也是我目前的实现所允许的!另外,“您当前的实现不允许的是同时发生其中两个操作”,如果我错了,请纠正我,但这不取决于调用方吗?或者我是否需要在我的存储类中以某种方式覆盖该方法?delete(6)add(8)delete(8)add(8)run
1赞 Stephen C 11/13/2023
一般来说,说“我想让这个线程安全”是不够的。您还需要指定在多线程用例中需要保留的正确性标准。

答:

-2赞 Md Alif Al Amin 11/13/2023 #1

在对对象应用任何类型的操作时,您已经锁定了该对象。此代码可能会有所帮助。

import java.util.HashMap;
import java.util.Map;

class MyStorage<T> {
    private final Map<T, Object> locks = new HashMap<>();
    private final Map<T, BSTreeNode> data = new HashMap<>();

    public boolean add(T value) {
        synchronized (getLock(value)) {
            // Add logic here
        }
        return true;
    }

    public boolean delete(T value) {
        synchronized (getLock(value)) {

        }
        return true;
    }

    public boolean search(T value) {
        synchronized (getLock(value)) {
            // Search logic here
        }
        return true;
    }

    private Object getLock(T value) {
        // Ensure that there is a lock for each value
        return locks.computeIfAbsent(value, k -> new Object());
    }
}
1赞 Solomon Slow 11/13/2023 #2

我假设“BST”的意思是“二叉搜索树”。是吗?

一个线程擦除 6 个线程,另一个线程添加 8 是完全可以接受的,无论它们以什么顺序调用或中断,存储都会给出正确的结果。

线程是否有可能更新树中线程需要更新或跟踪的任何链接?反之亦然,线程是否有可能更新线程需要更新或关注的树中的任何链接?这就是您需要防止发生的。delete(6)add(8)add(8)delete(6)

有一个“最简单的方法”的名称,用于锁定整棵树。这称为“粗粒度锁定”。而你希望使用的称为“细粒度锁定”。https://en.wikipedia.org/wiki/Lock_(computer_science)#Granularity当细粒度锁定正确完成时,锁的争用就会减少,但会有更多的锁。

您还没有展示您的算法的任何部分,因此我无法真正评论您可能会做些什么不同的事情,但是链接数据结构中细粒度锁定的更具体名称是“交手锁定”。

我认为你应该在谷歌中搜索这个短语

评论

0赞 kesarling He-Him 11/14/2023
交手锁定正是我所需要的。谢谢!是的,BST=BinarySearchTree