.Net下的线程同步:Part 5 of N--(Interlocked && Volatile...)

其它同步对象


Interlocked

"A statement is Atomic if it executes as a single indivisible instruction. Strict atomicity precludes any possible preemption. In C#, a simple read or assignment on a field of 32 bits or less is atomic (assuming a 32-bit CPU). Operations on larger fields are non-atomic, as are statements that combine more than one read/write operation."

--Threading in C#, Joseph Albahari

 参考下述代码:

using System;
using System.Threading;

namespace AtomicTest
{
    class AtomicTest
    {
        static int x, y;
        static long z;

        static coid Test()
        {
            long myVar;

            x = 3;          //Atomic
            z = 3;          //Non atomic as Z is 64 bits
            myVar = z;      //Non atomic as Z is 64 bits
            y += x;         //Non atomic read and write
            x++;            //Non atomic read and write
        }
    }
}

解决上述问题的一种方式是使用lock关键字。但是,.net其实提供了一种更简单也更快的方式,那就是InterlockedInterlocked 比lock更安全,因为Interlocked 不会阻塞。

MSDN :

"The methods of this class help protect against errors that can occur when the scheduler switches contexts while a thread is updating a variable that can be accessed by other threads, or when two threads are executing concurrently on separate processors. The members of this class do not throw exceptions."

         下面是一个使用 Interlocked 类的示例:

using System;
using System.Threading;

namespace InterlockedTest
{
    class Program
    {
        static long currentValue;

        static void Main(string[] args)
        {
            //simple increment/decrement operations
            Interlocked.Increment(ref currentValue);
            Console.WriteLine(String.Format(
                "The value of currentValue is {0}", 
                Interlocked.Read(ref currentValue)));

            Interlocked.Decrement(ref currentValue);
            Console.WriteLine(String.Format(
                "The value of currentValue is {0}", 
                Interlocked.Read(ref currentValue)));

            Interlocked.Add(ref currentValue, 5);
            Console.WriteLine(String.Format(
                "The value of currentValue is {0}", 
                Interlocked.Read(ref currentValue)));



            //read a 64 bit value
            Console.WriteLine(String.Format(
                "The value of currentValue is {0}", 
                Interlocked.Read(ref currentValue)));


            Console.ReadLine();
        }
    }
}

结果如下:



Interlocked 类还提供其它方法:

  • CompareExchange(location1,value,comparand): 如果comparand和位于location1的值相同,则将value存储于location1。否则不做任何操作,CompareExchange的返回值为location1的原值,不论交换是否发生。
  • Exchange(location1,value): 将value赋予位于location1的变量,同时返回原有的值,整个过程是个原子操作。

这两个函数可以代替Monitor或者Mutex等内核锁来实现lock-free(wait-free)算法和数据结构。

Volatile

volatile 关键字表明被其修饰的变量可以为OS,硬件,或者并发的线程修改。

MSDN :

"The system always reads the current value of a volatile object at the point it is requested, even if the previous instruction asked for a value from the same object. Also, the value of the object is written immediately on assignment.

The volatile modifier is usually used for a field that is accessed by multiple threads without using thelock statement to serialize access. Using thevolatile modifier ensures that one thread retrieves the most up-to-date value written by another thread."

ReaderWriterLockSlim

常见的情况是,对于某类型其读操作是线程安全的,但是更新操作却不是。尽管可以通过lock关键字来弥补,但是这样限制性又太强。ReaderWriterLockSlim 就适用于这种情况。

ReaderWriterLockSlim class (.NET 3.5) 提供两种锁:  read lock 和 write lock. write lock 是独占的, 而read lock则可以与其他read lock 兼容.

如果某个线程持有write lock,则将阻塞所有其它试图read lock 和 write lock的线程。如果没有线程锁定write lock,则任意数量的线程可以获取read lock。

ReaderWriterLockSlim class提供的主要方法如下:

  • EnterReadLock (*)
  • ExitReadLock
  • EnterWriteLock (*)
  • ExitWriteLock (*)

示例(original example courtesy of Threading in C#, Joseph Albahari):

using System;
using System;
using System.Threading;
using System.Collections.Generic;

namespace ReaderWriterLockSlimTest
{
    /// <summary>
    /// This simple class demonstrates the usage a Reader/Writer 
    /// situation, using the ReaderWriterLockSlim class
    /// </summary>
    class Program
    {
        static ReaderWriterLockSlim rw = new ReaderWriterLockSlim();
        static List<int> items = new List<int>();
        static Random rand = new Random();

        static void Main(string[] args)
        {
            //start some readers
            new Thread(Read).Start("R1");
            new Thread(Read).Start("R2");
            new Thread(Read).Start("R3");

            //start some writers
            new Thread(Write).Start("W1");
            new Thread(Write).Start("W2");
        }

        static void Read(object threadID)
        {
            //do read
            while (true)
            {
                try
                {
                    rw.EnterReadLock();
                    Console.WriteLine("Thread " + threadID +
                        " reading common source");
                    foreach (int i in items)
                        Thread.Sleep(10);
                }
                finally
                {
                    rw.ExitReadLock();
                }
            }
        }

        static void Write(object threadID)
        {
            //do write
            while (true)
            {
                int newNumber = GetRandom(100);
                try
                {
                    rw.EnterWriteLock();
                    items.Add(newNumber);
                }
                finally
                {
                    rw.ExitWriteLock();
                    Console.WriteLine("Thread " + threadID +
                        " added " + newNumber);
                    Thread.Sleep(100);
                }
            }
        }

        static int GetRandom(int max)
        {
            //lock on the Random object
            lock (rand)
                return rand.Next(max);
        }
    }
}

结果如下:

System.Threading域名下还有一个ReaderWriterLock 类。下面是 MSDN 中关于ReaderWriterLockSlim (.NET 3.5)和ReaderWriterLock (.NET 2.0)的区别:

ReaderWriterLockSlim is similar to ReaderWriterLock, but it has simplified rules for recursion and for upgrading and downgrading lock state.ReaderWriterLockSlim avoids many cases of potential deadlock. In addition, the performance ofReaderWriterLockSlim is significantly better thanReaderWriterLock.ReaderWriterLockSlim is recommended for all new development.


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值