2016-12-10 5 views
3

Ich versuche, das Producer-Consumer-Concurrency-Problem mit Semaphoren in C# zu lösen (ich glaube, ich habe es gelöst: Ich glaube, dass die Semaphoren das Problem des gegenseitigen Ausschlusses lösen und gleichzeitig das Synchronisationsproblem lösen der zwei Fäden).
Mein Problem ist:
Ich verstehe nicht, warum meine Variable "Daten" durch Referenz (Ref) in der Producer-Instanz und in der Consumer-Instanz nicht im Speicher freigegeben ist.
Ich habe C# nur für ein paar Tage gelernt und ich bin mir ziemlich sicher, dass ich das Schlüsselwort "ref" nicht richtig verstanden habe. Bitte bei mir tragen.
Der Code:Shared Memory in C# Parallelität

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Threading; 
using System.Threading.Tasks; 

namespace ProducerConsumer 
{ 
class Program 
{ 
    static void Main(string[] args) 
    { 
     Semaphore hasData = new Semaphore(0, 1); //There is no data when the program starts 
     Semaphore hasSpace = new Semaphore(1, 1); //There is space to produce 
     int data = 0;        //the variable "data" will be a shared variable 
     Producer producer = new Producer(hasData, hasSpace, ref data); 
     Consumer consumer = new Consumer(hasData, hasSpace, ref data); 
     Thread producerThread = new Thread(new ThreadStart(producer.Produce)); 
     Thread consumerThread = new Thread(new ThreadStart(consumer.Consume)); 
     producerThread.Start(); 
     consumerThread.Start(); 
    } 
} 
class Producer 
{ 
    static Random rnd = new Random(); 
    private Semaphore hasData; 
    private Semaphore hasSpace; 
    private int data; 
    public Producer(Semaphore hasData, Semaphore hasSpace, ref int data) 
    { 
     this.hasData = hasData; 
     this.hasSpace = hasSpace; 
     this.data = data; 
    } 
    public void Produce() 
    { 
     while (true) 
     { 
      hasSpace.WaitOne(); 
      this.data = rnd.Next(0, 100); 
      Console.WriteLine("The producer made: " + this.data); 
      Thread.Sleep(5000); 
      hasData.Release(); 
     } 
    } 
} 
class Consumer 
{ 
    private Semaphore hasData; 
    private Semaphore hasSpace; 
    private int data; 
    public Consumer(Semaphore hasData, Semaphore hasSpace, ref int data) 
    { 
     this.hasData = hasData; 
     this.hasSpace = hasSpace; 
     this.data = data; 
    } 
    public void Consume() 
    { 
     while (true) 
     { 
      hasData.WaitOne(); 
      Console.WriteLine("The consumer got: " + this.data); 
      Thread.Sleep(5000); 
      hasSpace.Release(); 
     } 
    } 
} 
} 

Der Ausgang:
enter image description here

Wie Sie der Produzent sehen kann, ist in einem anderen Teil des Speichers Herstellung und die Verbraucher an einem anderen Teil des Speichers an.
Ich würde auch gerne wissen, wie man dieses Problem löst.
Danke!

+0

'this.data = Daten,' dann sind Ihre Daten durch ref nicht mehr. es kopiert 'data' in' this.data' –

+0

aber kopiert es nur den Wert? – 00Mugen00

+0

Gibt es eine Möglichkeit, dass this.data auf denselben Speicher verweist wie die Variable "data", die im Konstruktor des Producers als Referenz übergeben wird. – 00Mugen00

Antwort

0

Obwohl Sie data durch ref übergeben, wird der Wert in data Feld kopiert. weil int ein Werttyp ist kein Referenztyp.

Sie können die Wrapper-Klasse verwenden, um den Wert innerhalb des Referenztyps zu halten.

class RefVal<T> 
{ 
    public T Value { get; set; } 

    public RefVal(T value) 
    { 
     Value = value; 
    } 

    public override string ToString() 
    { 
     return Value.ToString(); 
    } 
} 

Und dann haben Sie es zu verwenden, anstatt int wie dies diese

RefVal<int> data = new RefVal<int>(0); //the variable "data" will be a shared variable 
Producer producer = new Producer(hasData, hasSpace, data); 
Consumer consumer = new Consumer(hasData, hasSpace, data); 

// ... 

class Producer 
{ 
    private RefVal<int> data; 

    // ... 

    public Producer(Semaphore hasData, Semaphore hasSpace, RefVal<int> data) 
    { 
     this.hasData = hasData; 
     this.hasSpace = hasSpace; 
     this.data = data; 
    } 
    public void Produce() 
    { 
     while (true) 
     { 
      hasSpace.WaitOne(); 
      this.data.Value = rnd.Next(0, 100); // set value to .Value 
      Console.WriteLine("The producer made: " + this.data); 
      Thread.Sleep(5000); 
      hasData.Release(); 
     } 
    } 
} 
class Consumer 
{ 
    private Semaphore hasData; 
    private Semaphore hasSpace; 
    private RefVal<int> data; 
    public Consumer(Semaphore hasData, Semaphore hasSpace, RefVal<int> data) 
    { 
     this.hasData = hasData; 
     this.hasSpace = hasSpace; 
     this.data = data; 
    } 

    //... 
} 
+0

Ich liebe die Idee. Ich werde es versuchen. Vielen Dank! – 00Mugen00

+0

Es funktioniert! Vielen Dank! – 00Mugen00

+0

froh, dass es geholfen hat. Bitte schön. –