1 00:00:03,180 --> 00:00:14,616 So going back to our producer consumer idea here. We're going to have a producer 2 00:00:14,616 --> 00:00:22,324 producing a value and a consumer consuming a value but now we have two consumers. And 3 00:00:22,324 --> 00:00:28,807 let's say we guarantee sequential consistency in our model. What breaks 4 00:00:28,807 --> 00:00:33,349 here? Well, if we guarantee sequential consistency, and we have a reader excuse, 5 00:00:33,349 --> 00:00:38,657 me, a producer and a consumer. That code sequence that I showed originally actually 6 00:00:38,657 --> 00:00:43,036 works out pretty well. Because we are not having any of those reordering of, let's 7 00:00:43,036 --> 00:00:47,137 say, this store and like this read or something. We're not actually getting 8 00:00:47,137 --> 00:00:51,128 those reorderings to happen, because sequential consistency has basically 9 00:00:51,128 --> 00:00:57,947 outlawed those. But all of a sudden if we have two consumers. And we go and stare at 10 00:00:57,947 --> 00:01:02,920 this piece of code carefully. This is our original piece of code. One of the things 11 00:01:02,920 --> 00:01:10,622 that happens is they check the head, pointer To see if it's equal to tall which 12 00:01:10,622 --> 00:01:15,560 means something invaluable. And if two, process two threads or two processees try 13 00:01:15,560 --> 00:01:20,082 to do that simultaneously, they are going to fall through at this point. And what 14 00:01:20,082 --> 00:01:27,616 could happen, is they could both try to read the same value. So let's say you 15 00:01:27,616 --> 00:01:32,580 actually have two consumers, consumer one and consumer two that are interleaved and 16 00:01:32,580 --> 00:01:37,484 we just basically do every other cycle executing every other instruction from the 17 00:01:37,484 --> 00:01:41,790 two copies of this consumer code interleaved. And, what's going to happen 18 00:01:41,790 --> 00:01:48,091 is they're going to read the same value out of the queue. Well, we really don't 19 00:01:48,091 --> 00:01:57,874 want that. We want to somehow guarantee that this block here happens while no 20 00:01:57,874 --> 00:02:05,010 other threads or processes are executing the same block here of code. So we're 21 00:02:05,010 --> 00:02:10,940 gonna introduce this notion of locks and semaphores, and we'll talk more about it 22 00:02:10,940 --> 00:02:20,100 next time, but the basic idea is that you have, something. Now, it could be a piece 23 00:02:20,100 --> 00:02:26,805 of hardware or it could be a memory location which guards the execution of a 24 00:02:26,805 --> 00:02:34,016 critical section or a piece of code. And you can either have those be such that 25 00:02:34,016 --> 00:02:39,847 only one process or one processor can execute that piece of code at the same 26 00:02:39,847 --> 00:02:45,754 time. That's mutual exclusion and that's, a mutex. Or you can think of a more 27 00:02:45,754 --> 00:02:51,889 general notion of a semaphore. Where you can have some number N, where N processes 28 00:02:51,889 --> 00:02:57,250 can enter a critical section concurrently. An example of that as I said before in 29 00:02:57,250 --> 00:03:01,612 class, why we want to do that, is let's say you have two sets of resources. Like, 30 00:03:01,612 --> 00:03:06,477 two outbound queues on your network card. And you have P processors and you want two 31 00:03:06,477 --> 00:03:10,951 people to try to go use it at the same time. But you don't care which two. But it 32 00:03:10,951 --> 00:03:15,257 can't be three. You need something that's more general than just a mutex or a 33 00:03:15,257 --> 00:03:19,675 single-user lock. Okay, so we're gonna stop here and we'll talk more about locks 34 00:03:19,675 --> 00:03:24,149 and semaphores including hopefully some people speak Dutch. Because that's, 35 00:03:23,757 --> 00:03:27,840 because we need to know that to get the names of some of these semaphores.