2016-03-07 60 views
1

我对线程一般都比较陌生,我想在C#中尝试一下。我正在试图对每20秒钟衰减一次并每10秒重新充满一次的吨位进行基本模拟。从我读的内容来看,线程安全是我需要考虑的事情,因为有两个线程;一个用于将可变吨位衰减160,另一个用于对吨位增加一个随机数并且由于他们正在对变量吨位进行交易,所以我应该确保它们的访问是正确的。如何在无限循环中使用线程锁?

我读到如何使用锁(对象),我理解简单线程示例的概念,但是如何将它用于永久运行的2个线程并且必须及时调整吨位?

这是我的,但是当我锁定整个循环,其他线程永远不会产生。或者我有错误的代码结构?

public double tonnage = 1000; 
private object x = new object(); 

//Starts the simulation, runs forever until user ends the simulation 
private void btnStart_Click(object sender, EventArgs e) 
{ 
    //Decay Tonnage 
    Thread decayTonnageThread = new Thread(() => decayTonnage (tonnage)); 
    decayTonnageThread .Start(); 

    //Add Tonnage 
    Thread addTonnageThread = new Thread(() => addTonnage (tonnage)); 
    addTonnageThread .Start(); 
} 

//I want to decay the tonnage every 20 seconds 
public void decayTonnage (double tonnage) 
    { 
     lock(x) 
     { 
      while (true) 
      { 
       tonnage = tonnage - 160; 
       Thread.Sleep(20000); 
      } 
     } 
    } 

//Add to the tonnage every 10 seconds 
public void addTonnage (double tonnage) 
    { 
     lock(x) 
     { 
      while (true) 
      { 
       Random random = new Random(); 
       double randomNumber = random.Next(97, 102); 
       tonnage = tonnage + randomNumber; 
       Thread.Sleep(10000); 
      } 
     } 
    } 
+5

你会想要在循环内部进行锁定,而不是在外部。 – adv12

+1

仅在更改吨位时使用锁定,排除其余代码。也许使用[Interlocked类](https://msdn.microsoft.com/nl-nl/library/system.threading.interlocked(v = vs.110).aspx)可能是一个好主意 –

+0

@ adv12它工作谢谢! –

回答

5

您希望锁越小越好,只能在与共享对象交互的行的周围,而不是整个循环。另外,将Random random = new Random();放在while循环is a bad habit to have中,您应该只创建一个随机实例并在循环之外初始化它。

//I want to decay the tonnage every 20 seconds 
public void decayTonnage (double tonnage) 
{ 

     while (true) 
     { 
      lock(x) 
      { 
       tonnage = tonnage - 160; 
      } 
      Thread.Sleep(20000); 
     } 
} 

//Add to the tonnage every 10 seconds 
public void addTonnage (double tonnage) 
{ 

     Random random = new Random(); 
     while (true) 
     { 
      double randomNumber = random.Next(97, 102); 
      lock(x) 
      { 
       tonnage = tonnage + randomNumber; 
      } 
      Thread.Sleep(10000); 
     } 
} 

另外,我认为你是对一些类型的赋值这样做的,必须使用线程,但如果我这样做真正的我不会使用与循环线+一个Sleep可言,而使用两个定时器,每20秒发射一次,每10秒发射一次。根据type of timer you use,您可能或可能不需要使用锁。

+0

我会试试这个,是的,我认为只锁定与共享对象交互的行是有意义的。这不是一项任务,它的工作(尚未生产)。我试图模拟如果用户改变了一些变量会发生什么,所以我去了线程。我会研究你使用计时器的建议,谢谢。 –