none
关于线程同步的问题? RRS feed

  • 问题

  • 如何实现若干线程可以同时执行,但必须等待另一线程执行完,这一线程要执行也必须等待若干线程全部执行完?
    假设有线程A、B、C,线程C要执行,如果A或B在执行,必须等待线程AB线程执行完,线程AB要执行,如果线程C在执行,必须等待线程C执行完。
    2009年5月9日 9:05

答案

  • mutex 速度是很快 但是会影响windows 其他的程序哦。。。。

     

    readwritelockslim 很好地


    有效回复过700 撒花
    • 已标记为答案 yjss 2009年5月18日 3:35
    2009年5月13日 5:34
    版主
  • 你这是读写锁  请用 .net 3.5 的  readwritelock slim


    我给你个我自己写的 dicrionary 实现    这个dictionary 就是一个水井     有人写的时候就会暂时锁住所有读的部分
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.ComponentModel;
    using System.ComponentModel.Design;
    using System.Runtime.InteropServices;
    using System.Diagnostics;
    using System.Threading;
    using System.Security.Permissions;
    
    
    
    namespace System.Collections.Generic.Sync
    {
    
      public   class SyncDictionary<TKey, TValue> : Dictionary<TKey, TValue>
        {
            private ReaderWriterLockSlim _lock = new ReaderWriterLockSlim();
    
            public new void Add(TKey key, TValue value)
            {
                _lock.EnterWriteLock();
                base.Add(key, value);
                _lock.ExitWriteLock();
    
            }
    
            public new void Clear()
            {
                _lock.EnterWriteLock();
                base.Clear();
                _lock.ExitWriteLock();
    
            }
            public new bool ContainsKey(TKey key)
            {
                _lock.EnterReadLock();
                var rv = base.ContainsKey(key);
                _lock.ExitReadLock();
                return rv;
            }
    
    
    
            public new bool ContainsValue(TValue value)
            {
                _lock.EnterReadLock();
                var rv = base.ContainsValue(value);
                _lock.ExitReadLock();
                return rv;
            }
    
    
            public new Dictionary<TKey, TValue>.Enumerator GetEnumerator()
            {
                _lock.EnterReadLock();
                var rv = new Dictionary<TKey, TValue>(this).GetEnumerator();
                _lock.ExitReadLock();
                return rv;
            }
            public new bool Remove(TKey key)
            {
                _lock.EnterWriteLock();
                var rv = base.Remove(key);
                _lock.ExitWriteLock();
                return rv;
    
            }
            public new bool TryGetValue(TKey key, out TValue value)
            {
                _lock.EnterReadLock();
                var rv = base.TryGetValue(key, out value);
                _lock.ExitReadLock();
                return rv;
    
            }
    
    
            public new int Count
            {
                get
                {
                    _lock.EnterReadLock();
                    var rv = base.Count;
                    _lock.ExitReadLock();
                    return rv;
                }
    
            }
    
    
            public new TValue this[TKey key]
            {
                get
                {
                    _lock.EnterReadLock();
                    var rv = base[key];
                    _lock.ExitReadLock();
                    return rv;
                }
                set
                {
                    _lock.EnterWriteLock();
                    base[key] = value;
                    _lock.ExitWriteLock();
           
                }
            }
    
    
            public  new Generic.Dictionary <TKey, TValue>.KeyCollection Keys
            {
                get
                {
    
                    _lock.EnterReadLock();
                    var rv = base.Keys;
                    _lock.ExitReadLock();
                    return rv;
                }
    
            }
    
            public new Generic.Dictionary<TKey, TValue>.ValueCollection Values
            {
                get
                {
                    _lock.EnterReadLock();
                    var rv = base.Values;
                    _lock.ExitReadLock();
                    return rv;
                }
    
            }
     
    
     
    
       
    
    
    
        }
    }
    

    有效回复过700 撒花
    • 已标记为答案 yjss 2009年5月18日 3:35
    2009年5月18日 3:12
    版主

全部回复

  • 不使用线程就是这样的,必须等到上一步的代码执行完了才会执行下一下。如果你是说多线程同步的话可以使用 lock 产键字.

    lock 关键字可以用来确保代码块完成运行,而不会被其他线程中断。这是通过在代码块运行期间为给定对象获取互斥锁来实现的。lock 语句以关键字 lock 开头,它有一个作为参数的对象,在该参数的后面还有一个一次只能由一个线程执行的代码块。例如:

    public class TestThreading
    {
        private System.Object lockThis = new System.Object();
        public void Function()
        {
            lock (lockThis)
            {
                // Access thread-sensitive resources.
            }
        }
    }
    


    知识改变命运,奋斗成就人生!
    2009年5月9日 9:52
    版主
  • 你好!
         官方文档里有很详细的讲述,希望对你有帮助:
    http://msdn.microsoft.com/zh-cn/library/ms173179(VS.80).aspx
    周雪峰
    2009年5月9日 10:18
    版主
  • 不使用线程就是这样的,必须等到上一步的代码执行完了才会执行下一下。如果你是说多线程同步的话可以使用 lock 产键字.

    lock 关键字可以用来确保代码块完成运行,而不会被其他线程中断。这是通过在代码块运行期间为给定对象获取互斥锁来实现的。lock 语句以关键字 lock 开头,它有一个作为参数的对象,在该参数的后面还有一个一次只能由一个线程执行的代码块。例如:

    public class TestThreading
    
    {
    
        private System.Object lockThis = new System.Object();
    
        public void Function()
    
        {
    
            lock (lockThis)
    
            {
    
                // Access thread-sensitive resources.
    
            }
    
        }
    
    }
    
    


    知识改变命运,奋斗成就人生!

    若干线程是可以同时执行的(也就是线程A和B),所以lock 不能满足要求!
    2009年5月9日 10:52
  • 你是不是在解决 a,b 同时访问或更新同一个资源?
    知识改变命运,奋斗成就人生!
    2009年5月9日 10:53
    版主
  • 还要 A 执行完了,执行 B, 了完了,再执行 C?
    知识改变命运,奋斗成就人生!
    2009年5月9日 10:54
    版主
  • 你是不是在解决 a,b 同时访问或更新同一个资源?
    知识改变命运,奋斗成就人生!

    A和B可以同时执行,但A和C以及B和C只能执行其中一个
    2009年5月9日 11:18
  • 你可以这样想,在启动 A, B, C 线程前都加一个判断,如 A 启动前检查 C 是否正在运行,如果未运行则 A 启动, 如果 C 已启动 A 则继续等待. B, C 同理
    知识改变命运,奋斗成就人生!
    2009年5月9日 11:23
    版主
  • 你可以这样想,在启动 A, B, C 线程前都加一个判断,如 A 启动前检查 C 是否正在运行,如果未运行则 A 启动, 如果 C 已启动 A 则继续等待. B, C 同理
    知识改变命运,奋斗成就人生!

    “启动前判断,已启动就继续等待”难道用循环判断加Sleep,不然怎么等待?如果有很多线程将会严重影响效率。

    难道没有提供这样一个同步对象:一个线程要等待其它所有线程执行完成才能继续执行,而其它线程则可以同时执行!
    2009年5月9日 11:33
  • 启动线程的方法只有一个,等待也只有一个,就算你一开始就打开所有线程,在线程中来做判断来确定是否开始真实的业务逻辑,但这样的方法你真的试过吗?前提 Sleep 的时间不要太短, 线程数量不超过机器的处理瓶颈,
    知识改变命运,奋斗成就人生!
    2009年5月9日 11:45
    版主
  • 启动线程的方法只有一个,等待也只有一个,就算你一开始就打开所有线程,在线程中来做判断来确定是否开始真实的业务逻辑,但这样的方法你真的试过吗?前提 Sleep 的时间不要太短, 线程数量不超过机器的处理瓶颈,
    知识改变命运,奋斗成就人生!

    不管怎样用循环加 Sleep 我个人觉得是肯定不是什么好方法,WaitHandle.WaitAll好像可以实现,不过好像要一个WaitHandle的数组,每开一个线程就要往里面加一个WaitHandle,有没有比这更好的方法?
    2009年5月9日 12:00
  • 可以试试在一个线程完成后通过回调来打开一下个线程
    知识改变命运,奋斗成就人生!
    2009年5月9日 12:03
    版主
  • 2009年5月9日 14:02
    版主
  • 用互斥量就可以了


    MSMVP VC++

    能说一下实现原理吗?或直接贴出代码,谢谢!
    2009年5月12日 11:30
  • 文档里不是都有么
    MSMVP VC++
    2009年5月12日 13:23
    版主
  • mutex 速度是很快 但是会影响windows 其他的程序哦。。。。

     

    readwritelockslim 很好地


    有效回复过700 撒花
    • 已标记为答案 yjss 2009年5月18日 3:35
    2009年5月13日 5:34
    版主
  • 文档里不是都有么
    MSMVP VC++

    当两个或更多线程需要同时访问一个共享资源时,系统需要使用同步机制来确保一次只有一个线程使用该资源Mutex 是同步基元,它只向一个线程授予对共享资源的独占访问权。如果一个线程获取了互斥体,则要获取该互斥体的第二个线程将被挂起,直到第一个线程释放该互斥体。

    以上是关于互斥量的说明,不知道是不是我没能理解Mutex,它怎么能直接实现“一个线程要等待其它所有线程执行完成才能继续执行,而其它线程则可以同时执行”!这其中的“其它线程则可以同时执行”说明有多个线程同时在执行,而Mutex它“只向一个线程授予对共享资源的独占访问权

    我举个例子来说明我要实现的功能吧:

    村里有个水井,可以同时有多个人一起打水,村长需要对水井进行维修时,要等待其它正在打水的人把水打完,而村长正在维修水井时,其它人需要打水,必需等待村长维修完毕。
    2009年5月18日 2:00
  • 看执行的代码怎么写了
    比如你用互斥量保护一个线程链表的写操作,每个线程退出时将自己从链表中去掉,到链表为空的时候再开始执行代码

    MSMVP VC++
    2009年5月18日 3:07
    版主
  • 你这是读写锁  请用 .net 3.5 的  readwritelock slim


    我给你个我自己写的 dicrionary 实现    这个dictionary 就是一个水井     有人写的时候就会暂时锁住所有读的部分
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.ComponentModel;
    using System.ComponentModel.Design;
    using System.Runtime.InteropServices;
    using System.Diagnostics;
    using System.Threading;
    using System.Security.Permissions;
    
    
    
    namespace System.Collections.Generic.Sync
    {
    
      public   class SyncDictionary<TKey, TValue> : Dictionary<TKey, TValue>
        {
            private ReaderWriterLockSlim _lock = new ReaderWriterLockSlim();
    
            public new void Add(TKey key, TValue value)
            {
                _lock.EnterWriteLock();
                base.Add(key, value);
                _lock.ExitWriteLock();
    
            }
    
            public new void Clear()
            {
                _lock.EnterWriteLock();
                base.Clear();
                _lock.ExitWriteLock();
    
            }
            public new bool ContainsKey(TKey key)
            {
                _lock.EnterReadLock();
                var rv = base.ContainsKey(key);
                _lock.ExitReadLock();
                return rv;
            }
    
    
    
            public new bool ContainsValue(TValue value)
            {
                _lock.EnterReadLock();
                var rv = base.ContainsValue(value);
                _lock.ExitReadLock();
                return rv;
            }
    
    
            public new Dictionary<TKey, TValue>.Enumerator GetEnumerator()
            {
                _lock.EnterReadLock();
                var rv = new Dictionary<TKey, TValue>(this).GetEnumerator();
                _lock.ExitReadLock();
                return rv;
            }
            public new bool Remove(TKey key)
            {
                _lock.EnterWriteLock();
                var rv = base.Remove(key);
                _lock.ExitWriteLock();
                return rv;
    
            }
            public new bool TryGetValue(TKey key, out TValue value)
            {
                _lock.EnterReadLock();
                var rv = base.TryGetValue(key, out value);
                _lock.ExitReadLock();
                return rv;
    
            }
    
    
            public new int Count
            {
                get
                {
                    _lock.EnterReadLock();
                    var rv = base.Count;
                    _lock.ExitReadLock();
                    return rv;
                }
    
            }
    
    
            public new TValue this[TKey key]
            {
                get
                {
                    _lock.EnterReadLock();
                    var rv = base[key];
                    _lock.ExitReadLock();
                    return rv;
                }
                set
                {
                    _lock.EnterWriteLock();
                    base[key] = value;
                    _lock.ExitWriteLock();
           
                }
            }
    
    
            public  new Generic.Dictionary <TKey, TValue>.KeyCollection Keys
            {
                get
                {
    
                    _lock.EnterReadLock();
                    var rv = base.Keys;
                    _lock.ExitReadLock();
                    return rv;
                }
    
            }
    
            public new Generic.Dictionary<TKey, TValue>.ValueCollection Values
            {
                get
                {
                    _lock.EnterReadLock();
                    var rv = base.Values;
                    _lock.ExitReadLock();
                    return rv;
                }
    
            }
     
    
     
    
       
    
    
    
        }
    }
    

    有效回复过700 撒花
    • 已标记为答案 yjss 2009年5月18日 3:35
    2009年5月18日 3:12
    版主
  • 不要忘记  lock(o){} 仅仅是  system.thread.monitor.enter (o)   .exit(o) 的简写

    就好像  using(o){} 是  o.dispose 的简写一样

    如果理解了lock(o){}
    就可以理解  


    取水
    _lock.EnterReadLock();
     _lock.ExitReadLock();

    修井
     _lock.EnterWriteLock();
     _lock.ExitWriteLock();


    有效回复过700 撒花
    2009年5月18日 3:19
    版主