什么是Java的getAndSet的c#等价物

时间:2017-03-16 15:13:45

标签: c# multithreading

我想编写与此java代码类似的c#代码:

=SUMPRODUCT((Table2[Employee Name]=”James Smith”)*(Table2[Task Month Year]")=”March 2017”/(COUNTIF(Table2[Employee Assigned Date],Table2[Employee Assigned Date]&"")))

3 个答案:

答案 0 :(得分:6)

我同意克里斯,Interlocked.Exchange(ref Int32, Int32),仅使用0,1是替代。

方法说明:

  

将32位有符号整数设置为指定值,并返回原始值作为原子操作。

AtomicBoolean.getAndSet()的说明:

  

以原子方式设置为给定值并返回先前的值。

可悲的是,Interlocked.Exchange()没有bool(并注意Interlocked.Exchange<T>()是参考类型!)

问题中给出的代码:

public class Syncer
{
    private int flag = 0;

    // Data is synced periodically and on user request
    // and these two calls may overlap
    public void SyncData()
    {
        if (Interlocked.Exchange(ref flag, 1) == 1)
        {
            return;
        }

        // Sync data...
        // It is enough that one thread is syncing data

        Interlocked.Exchange(ref flag, 0);
    }
}

答案 1 :(得分:2)

Interlocked.Exchange正是您要找的。不幸的是,如上所述,你不能将它与bool一起使用,这是一种耻辱。另一种方法是使用this answer中指出的int重载。

这个解决方案的“神奇数字”一直让我个人感到困扰。但是有一种方法可以创建一个引用类型,否则就像bool

public sealed class RefBool
{
    public static implicit operator bool( RefBool value )
    {
        return value != null;
    }

    public static implicit operator RefBool( bool value )
    {
        return value ? RefBool.True : RefBool.False;
    }

    public static bool operator true( RefBool value )
    {
        return value != null;
    }

    public static bool operator false( RefBool value )
    {
        return value == null;
    }

    public static readonly RefBool True = new RefBool();
    public static readonly RefBool False = null;

    private RefBool()
    {
    }
}

现在你的课程看起来像这样:

public class Syncer
{
    private RefBool mIsSyncInProgress = false;

    public void SyncData()
    {
        if (Interlocked.Exchange(ref mIsSyncInProgress, true))
        {
            return;
        }

        // Sync data...
        // It is enough that one thread is syncing data

        Interlocked.Exchange(ref mIsSyncInProgress, false);
    }
}

我发现在使用网站上更容易阅读。我发现这个解决方案并不完美,因为RefBool类有点奇怪。

您应该注意到我使用null作为错误状态。这是为了确保RefBool类型的变量只能是truefalse。如果我使用两个不同的实例来表示truefalse,那么RefBool也可能是null,这将是一个不确定的状态。

这样做的缺点是ToString无法正常工作(这就是为什么我没有打扰它的原因)。

答案 2 :(得分:1)

我建议您使用Montior.TryEnter(Object, Boolean),这最适合您的问题/示例。

但使用Monitor.TryEnter(Object)可以更好/更紧凑地编写(我会在第一个代码示例下面留下它作为建议)。

public class Syncer 
{
    private object lockObject = new object();

    // Data is synced periodically and on user request
    // and these two calls may overlap
    public void SyncData() {
        bool syncInProgress = false;
        try {
           Monitor.TryEnter(lockObject, ref syncInProgress); 
           if (syncInProgress) {
               // The critical section.

               // Sync data...
               // It is enough that one thread is syncing data
           }
           else {
               // The lock was not acquired.
               return;
           }
        }
        finally {
           // Ensure that the lock is released.
           if (syncInProgress) {
              Monitor.Exit(lockObject);
           }
        }
    }
}

清洁示例:

public class Syncer 
{
    private object lockObject = new object();

    // Data is synced periodically and on user request
    // and these two calls may overlap
    public void SyncData() {
        if(Monitor.TryEnter(lockObject)){
           try {
               // The critical section.

               // Sync data...
               // It is enough that one thread is syncing data
           }
           finally {
               // Ensure that the lock is released.
               Monitor.Exit(lockObject);
           }
        }
        else {
           // The lock was not acquired.
           return;
        }
    }
}