如果我只是想以线程安全的方式测试和设置标志,那么线程类是什么?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如果我只是想以线程安全的方式测试和设置标志,那么线程类是什么?相关的知识,希望对你有一定的参考价值。

我只是想做一个简单但通过线程安全的布尔测试(和设置),所以:

if(myBoolean==false)   //should not lock/wait!
{ 
     myBoolean=true;
     .....
}
else
{
     ....
}

我考虑过以下(虽然可能不正确,所以请在我误解的地方纠正我)

  • 使用Lock {if(myBoolean)...}构造看起来像是一种过度的方法。并且,它还在等待锁定变为空闲时锁定线程。我不想要这个。
  • AutoResetEvent类确实具有布尔状态的概念,但它用于指示正​​在等待的另一个线程。所以与我的情况无关
  • 信号量类有一个引用计数的概念(可能会限制对资源的访问量?)。所以可能不是我追求的。
  • 互斥类。据我所知,这与Lock原语相同

任何人都知道以有效的方式执行此操作的类/构造是什么?

答案

考虑一下Interlocked.CompareExchange

另一答案

答案(Intelocked.CompareExchange)已经给出,但这是我的用法示例:

private int _isDisposing;

public bool IsDisposing
{
    get
    {
        return this._isDisposing != 0;
    }
}

public void Dispose()
{
    // Side note: I may want to `return` instead of `throw`
    if (Interlocked.CompareExchange(ref _isDisposing, 1, 0) != 0)
        throw new InvalidOperationException("Dispose was recursively called.");

    try
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }
    finally
    {
        _isDisposing = 0;
    }
}
另一答案

你的问题有些含糊不清,但是 你可能正在寻找Interlocked课程。

编辑:您正在寻找Interlocked.CompareExchange

另一答案

要进行线程安全测试和设置操作,代码必须阻止其他线程。为避免锁定不必要,您可以使用test-and-test-and-set模式:

if (something) {
   lock(_sync) {
      if (something) {
         something = false;
         ...
      }
   }
}

第二个测试需要确保其他一些线程没有改变第一个测试和锁之间的值。

另一答案

对于集合,我使用“测试和添加”

        /// <summary>
    /// If h contains v then return true, else add v to h and return false.
    /// Thread safe on h.
    /// </summary>
    /// <param name="h"></param>
    /// <param name="v"></param>
    /// <returns></returns>
    bool TestAndAdd(HashSet<string> h, string v)
    {
        lock(h)
        {
            if(h.Contains(v))
            {
                return true;
            }
            h.Add(v);
            return false;
        }
    }

然后我可以测试和设置像..

    if (!TestAndAdd(usedCodes, mc.code))
另一答案

我多次遇到同样的问题,并且不认为我可以记住Interlocked.CompareAndChange()的最后一个参数是比较。这就是我想出来的。

using System.Threading;

public class AtomicFlag
{
    public const int SETVALUE = 1;
    public const int RESETVALUE = 0;

    /// <summary>
    /// Represents the current state of the flag.
    /// 0 means false (or reset).
    /// 1 means true (or set).
    /// </summary>
    private int Value;

    /// <summary>
    /// Creates an atomicflag with the specified default value.
    /// </summary>
    /// <param name="initialValue">AtomicFlag.SETVALUE or 
    /// AtomicFlag.RESETVALUE. Defaults to RESETVALUE.</param>
    public AtomicFlag(int initialValue = RESETVALUE)
    {
        Guard.AgainstUnsupportedValues<int>(initialValue, "initialValue",
           new int[] { SETVALUE, RESETVALUE });
        Value = initialValue;
    }


    public void Set()
    {
        Value = SETVALUE;
    }

    public void Reset()
    {
        Value = RESETVALUE;
    }


    public bool TestAndSet()
    {
        // Use Interlocked to test if the current value is RESETVALUE,
        // return true and set value to SETVALUE.
        //
        // From Interlocked.CompareExchange help:
        // public static int CompareExchange(
        //    ref int location1,
        //    int value,
        //    int comparand
        // )
        // where
        //  location1: The destination, whose value is compared with 
        //             comparand and possibly replaced.
        //  value:     The value that replaces the destination value if the
        //             comparison results in equality.
        //  comparand: The value that is compared to the value at
        //             location1. 
        return (RESETVALUE == Interlocked.CompareExchange(
            ref Value, SETVALUE, RESETVALUE));
    }

    public bool TestAndReset()
    {
        // If the current value is SETVALUE, return true and change value 
        // to RESETVALUE.
        return (SETVALUE ==
            Interlocked.CompareExchange(ref Value, RESETVALUE, SETVALUE));
    }
}

以上是关于如果我只是想以线程安全的方式测试和设置标志,那么线程类是什么?的主要内容,如果未能解决你的问题,请参考以下文章

java并发编程6.取消与关闭

跨越异步边界的布尔标志的线程安全

Eclipse集成testng插件(离线安装方式)

TSQL SELECT TOP(如果标志=真则限制,否则无限)

线程封闭

如何测试应用程序的线程安全性?