- 01
- 02
- 03
- 04
- 05
- 06
- 07
- 08
- 09
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
class ProducerConsumer
{
private static Semaphore semaphore = new Semaphore(1, 2);
static object locker = new object();
static int product = 0;
private static bool work = true;
private static bool valueSet = false; // why??
private static void Producer() // производитель
{
while (work)
{
Console.WriteLine("Thread Producer start");
int sqr = 0;
semaphore.WaitOne(); // декрементируем счётчик семафора
for (int i = 0; i < 15; i++)
{
sqr = i * i;
}
lock (locker) // error
{
while (valueSet)
{
Thread.Yield();
}
product += sqr;
valueSet = true;
Console.WriteLine("Product put: " + sqr);
Console.WriteLine("Product now: " + product);
}
semaphore.Release(); // выход из семафора
Thread.Sleep(5000);
}
}
private static void Consumer() // потребитель
{
const int MAX = 5;
int[] arr = new int[MAX];
int result = 0;
Random rand = new Random();
while (work)
{
Console.WriteLine("Thread Consumer start");
semaphore.WaitOne();
for (int i = 0; i < 5; i++)
{
arr[i] = rand.Next(0, 1024);
}
for (int i = 0; i < 5; i++)
{
result += arr[i];
}
result /= 5;
while (!valueSet)
{
Thread.Yield();
}
lock (locker)
{
if (product - result > 0) // исключаем отриц.кол-ва продуктов
{
product -= result;
Console.WriteLine("Product get: " + result);
}
else
{
Console.WriteLine("Product < 0");
}
valueSet = false;
Console.WriteLine("Product now: " + product);
}
semaphore.Release();
Thread.Sleep(5000);
}
}
public static void Main()
{
Thread threadProducer = new Thread(Producer);
threadProducer.Start();
Thread threadConsumer = new Thread(Consumer);
threadConsumer.Start();
Thread.Sleep(5000);
Console.WriteLine("Main thread start.");
String str = System.Console.ReadLine();
Console.ReadKey();
}
}
brutushafens 29.06.2014 14:53 # +1
kegdan 29.06.2014 16:18 # +2
ну ахуеть теперь
Это. я так понимаю, на будущее.
Гениально
Sweet dreams
koodeer 29.06.2014 16:40 # +2
Использовать не volatile булевы поля для взаимодействия разных потоков - эпик фэйл.
bormand 29.06.2014 16:43 # +1
К сожалению, на x86 будет работать ;(
koodeer 29.06.2014 17:08 # +1
Единого мнения нет. Отчасти из-за различия в спецификации ECMA и реализации Microsoft. Например, в Mono будет одно поведение, в CLR другое. Для переносимого кода лучше сразу писать "по правилам": либо с volatile, либо другие меры предпринимать.
bormand 29.06.2014 17:12 # +3
kegdan 29.06.2014 16:55 # +1
kegdan 29.06.2014 19:39 # 0
kegdan 29.06.2014 19:59 # 0
bormand 29.06.2014 20:26 # 0
Это еще что такое. Цикл в коде ОП'а в этом плане лучше был, он хотя бы работал... А твой if один разок попробует подождать и попрет дальше. Совсем не айс.
Тут надо юзать что-то в духе wait/notify, или как оно у вас там в .net называется, M$ же любит переименовывать. Чтобы отправитель, добавляя элемент попутно будил получателя. А получатель, забирая элемент, будил отправителя.
bormand 29.06.2014 20:32 # 0
Monitor.Pulse и Monitor.Wait судя по всему.
kegdan 29.06.2014 21:03 # 0
Да, оно
bormand 29.06.2014 20:36 # 0
bormand 29.06.2014 20:49 # +2
kegdan 29.06.2014 21:04 # 0
bormand 29.06.2014 21:07 # +1
Лом с отверстием?
kegdan 29.06.2014 21:10 # +1
bormand 29.06.2014 21:13 # 0
kegdan 29.06.2014 21:16 # 0
Одно С моей стороны, другое - со стороны монитора. А через одно отвестие видно только лом.
Ашькальмэ!
bormand 29.06.2014 21:22 # 0
> А через одно отвестие видно только лом.
Это если оно не насквозь просверлено.
kegdan 29.06.2014 21:27 # +3
brutushafens 29.06.2014 22:26 # 0
kegdan 29.06.2014 22:34 # 0