2014-12-09 6 views
-1
static void Main(string[] args) 
    { 
      Test c = new Test(); 
      Thread oThread = new Thread(new ThreadStart(c.Lock)); 
      oThread.Start(); 

      Thread oThread2 = new Thread(new ThreadStart(c.AfterLock)); 
      oThread2.Start(); 

      Console.ReadLine(); 

    } 



public class Test 
{ 
    public Dictionary<string, string> dic = new Dictionary<string, string>(); 

    public void Lock() 
    { 
     lock (((IDictionary)dic).SyncRoot) 
     { 
      for (var i = 3; i < 200; i++) 
      { 
       Console.WriteLine(i.ToString()); 
       dic.Add(i.ToString(), i.ToString()); 
      } 
     } 

    } 
    public void AfterLock() 
    {    
     Console.WriteLine(dic["100"]); 
    } 
} 

AfterLock бросает исключение: Данный ключ не присутствовал в словареЧто не так с этим кодом блокировки?

выпо был заблокирован первым потоком? почему afterlock не дождался блокировки первых потоков?

+0

Я думаю, что нам понадобится 1. короткий полный * рабочий * пример, демонстрирующий проблему; * и * 2. точное описание «не работает» (например, точный тип и значение сообщения любого исключения). – Richard

+3

Не считая код, который на самом деле терпел неудачу, была плохая идея. –

+0

Что такое 'ThreadSafeDictionary'? Где замок, с которым вы столкнулись? Как вы ожидаете, что мы поможем вам с проблемой, если вы не покажете нам код, который терпит неудачу? –

ответ

1
  1. Вам нужно заблокировать вокруг доступа к объекту как при чтении данных, а также при записи данных. Синхронизация только записи небезопасны.

  2. Ничего не мешает вашему методу AfterLock от фактического запуска после вашего метода Lock. Он может так же легко запускаться до него, либо, поскольку вы неправильно синхронизируете чтение, они могут даже работать параллельно. Вам нужно добавить механизм синхронизации, чтобы предотвратить запуск этого метода после записи, если его выполнение зависит от первой записи, как это явно делается здесь.

1

Вы должны заблокировать выделенный объект, а не тот, который вы пытаетесь использовать.

class Example 
{ 
    private object cacheLock; 

    public static void Load() 
    { 
     // . . . 

     lock (cacheLock) 
     { 
      CacheTable = (ThreadSafeDictionary<String, 
       ThreadSafeDictionary<Object, Object>>)CacheTableTmp.Clone(); 
     } 
    } 
+0

«Частный объект readonly cacheLock = new Object();» может быть хорошей идеей, если у вас нет действительно веской причины для изменения cacheLock после того, как экземпляр Example уже был создан. – Gerino

+0

Нет ничего плохого в объекте, который он выбирает для блокировки. У него нет причин создавать здесь другой объект. – Servy

Смежные вопросы