C# 中的线程安全 Integer 类

问题描述 投票:0回答:1

在我的上一个问题之后,我尝试修复代码,但输出仍然不是我所期望的。我尝试定义一个线程安全整数:

using System;
using System.Threading;

public struct SInt
{
    private int _value;

    public SInt(int initialValue = 0)
    {
        _value = initialValue;
    }

    public int Value => Volatile.Read(ref _value); // Interlocked.CompareExchange(ref _value, 0, 0);

    // Add a value
    public int Add(int value) => Interlocked.Add(ref _value, value);

    // Subtract a value
    public int Subtract(int value) => Interlocked.Add(ref _value, -value);

    // Multiply the value
    public int Multiply(int value)
    {
        int initial, computed;
        do
        {
            initial = Value;
            computed = initial * value;
        }
        while (Interlocked.CompareExchange(ref _value, computed, initial) != initial);

        return computed;
    }

    // Divide the value
    public int Divide(int value)
    {
        if (value == 0)
            throw new DivideByZeroException();

        int initial, computed;
        do
        {
            initial = Value;
            computed = initial / value;
        }
        while (Interlocked.CompareExchange(ref _value, computed, initial) != initial);
        return computed;
    }

    // Increment the value
    public int Increment() => Interlocked.Increment(ref _value);

    // Decrement the value
    public int Decrement() => Interlocked.Decrement(ref _value);

    // Overloaded operators
    public static SInt operator +(SInt a, int b)
    {
        a.Add(b);
        return a;
    }

    public static SInt operator -(SInt a, int b)
    {
        a.Subtract(b);
        return a;
    }

    public static SInt operator *(SInt a, int b)
    {
        a.Multiply(b);
        return a;
    }

    public static SInt operator /(SInt a, int b)
    {
        a.Divide(b);
        return a;
    }

    public static SInt operator ++(SInt a)
    {
        a.Increment();
        return a;
    }

    public static SInt operator --(SInt a)
    {
        a.Decrement();
        return a;
    }

    // Equality operators
    public static bool operator ==(SInt a, SInt b) => a.Value == b.Value;

    public static bool operator !=(SInt a, SInt b) => a.Value != b.Value;

    // Comparison operators
    public static bool operator <(SInt a, SInt b) => a.Value < b.Value;
    public static bool operator <=(SInt a, SInt b) => a.Value <= b.Value;
    public static bool operator >(SInt a, SInt b) => a.Value > b.Value;
    public static bool operator >=(SInt a, SInt b) => a.Value >= b.Value;

    // Implicit conversion from int to SInt
    public static implicit operator SInt(int value) => new SInt(value);

    // Implicit conversion from SInt to int
    public static implicit operator int(SInt sInt) => sInt.Value;

    public override bool Equals(object? obj)
    {
        if (obj is SInt other)
        {
            return this == other;
        }
        return false;
    }

    public override int GetHashCode() => Value.GetHashCode();

    public override string ToString() => Value.ToString();
}

然后我重写了程序:

using System;
using System.Diagnostics;
using System.Threading;

class Program
{
    static void Main(string[] args)
    {
        List<Thread> threads = new List<Thread>();
        SInt s = 0;
        Stopwatch stopwatch = new Stopwatch();
        stopwatch.Start();
        for (int i = 0; i <1000; i++)
        {
            var t = new Thread(() =>
            {
                s++;
                Thread.Sleep(1000);
            });
            t.Priority = ThreadPriority.Highest;
            threads.Add(t);
            t.Start();
        }
        foreach (var t in threads)
            t.Join();
        stopwatch.Stop();
        Console.WriteLine($"Time: {stopwatch.ElapsedMilliseconds / 1000.0} Seconds");
        Console.WriteLine(s);
        Console.WriteLine(threads.Count(t => t.ThreadState == System.Threading.ThreadState.Stopped));
        Console.ReadKey();
    }
}

我的笔记本电脑中的输出:

Time: 85.16 Seconds
989
1000

我预计 989 是 1000。

怎么了?

c# multithreading
1个回答
0
投票

在 C# 中,

struct
是值类型。

因此您将其退回的地方,例如在:

public static SInt operator ++(SInt a)
{
    a.Increment();
    return a;
}

您实际上归还了一份副本。

如果

SInt
是一个类,它的行为会像您期望的那样,返回对当前实例的引用。

© www.soinside.com 2019 - 2024. All rights reserved.