NATE HARDISON: When you've got multiple programs open on a
computer, it seems like everything's
running at the same time.
For example, you might be working in a web browser like
Firefox or Internet Explorer, listening to music on iTunes,
and writing an essay with Word.
However, under the hood, the programs actually
run one at a time.
It's the job of the operating system, Windows, Mac OSX, or
Linux, to manage each of these separate processes, as the
programs are known, and switch between them so that when you
go from checking your Facebook page to working on your essay
again, Word is the one that's running.
>> Sometimes, though, we want programs themselves to be able
to do multiple things like this, too.
If you're like me, you probably have a bunch of
different tabs open in your web browser, one for email,
one with a calendar, and so on.
We could treat each tab as a separate program or process,
like Google Chrome does, but many programs use a
lighter-weight version of a process called a thread.
>> A thread is just another unit of processing ,a set of
instructions or code that can "run", quote unquote,
concurrently with other threads.
This is what makes it possible for you to browse Facebook
while listening to me in the background or to have two
YouTube videos playing at the same time.
So, this general topic, known as concurrency, typically
doesn't come up so early in computer science courses
because the lower-level details require discussion of
operating systems and the like.
However, the programming language we use at the
beginning of CS50, Scratch, provides some nifty tools to
make it easier to write programs with multiple things
going on at once.
>> When you build Scratch programs, you're constantly
working with threads.
Each Scratch script, which is a code block that begins with
one of the "when" puzzle pieces, can be thought of
as a separate thread.
Let's look at a simple Scratch program to see how this works.
>> Here, we've got a fish object, or sprite, with two scripts
that both start when we click the little green flag button.
The first script controls the fish's motion.
When the green flag is clicked, the fish gets placed
on the left side of the screen, called the stage,
facing to the right.
Then, in a set of instructions that'll run forever, until we
stop the program, the fish glides to the right side,
turns around, goes back to the left side, and
turns around again.
The second script controls the fish's thought process.
It turns out that this is a hungry fish.
So after waiting for 3 seconds, the fish will think,
"I'm hungry," for a fourth second.
This script also runs forever.
And as we see, from running the program by clicking the
green flag, both scripts appear to execute
simultaneously.
The fish moves and thinks at the same time.
>> Since the poor fish looks so hungry, let's add in some
cheesy puffs for it to eat.
Hopefully they won't disintegrate in the water.
When we add in a second sprite, we'll also be able to
add in scripts corresponding to that sprite.
And, hence, there'll be another set of
threads that'll run.
To give the user of our program control over when the
hungry fish gets food, let's say that whenever the Space
Bar is hit, cheesy puffs appear on the stage for the
fish to eat.
Before we hit the Space Bar, we'll want to keep the cheesy
puffs hidden so that the fish can't see them.
To do this, we'll need a couple of scripts for the
cheesy puffs sprite.
The first script, the green flag, will just hide the food.
Unlike the other scripts we've written, this one won't keep
running forever.
It will start and finish very quickly, right when we click
the green flag button.
>> The next script we have will wait for the Space Bar to be
pressed before executing.
We can call waiting for user input "waiting" or "listening"
for an event.
And the code that executes when an event is received or
heard is called event handling code.
Our Space Bar event handler will show the cheesy puffs on
the screen so that the fish can eat them.
At this point, everything's looking good.
>> The next thing we need to do is to figure out how to get
the fish to realize that there's food to eat.
Let's add another thread to the fish that constantly
checks whether or not it's touching the cheesy puffs.
We do this in a separate thread since that way we can
constantly check for food.
Otherwise, we'd only be able to periodically check for food
in between gliding, turning around, waiting, or thinking.
>> OK.
Now let's run our Scratch program.
As expected, the food immediately hides and the
hungry fish swims back and forth just like before.
When we hit the Space Bar, the cheesy puffs come into view,
and the hungry fish says whoo.
But wait, that's weird.
How come the fish's "I'm hungry" thought interrupts the
other stuff?
This is because we didn't establish any coordination
between the three fish scripts.
Each is running in its own thread, oblivious to what the
others are doing.
Let's fix this before we move on.
>> Coordination between threads is a tricky task since we
don't have explicit control over when each thread runs or
doesn't run.
To send a message from one thread to another, we'll need
to use a variable that we can set, or write, in one thread
and read in the other.
Let's create a variable called foodFound that we can set to
true when the fish runs into the cheesy puffs.
Well, of course, we want to make sure that we set it to
false initially.
Then, in the fish's thinking thread, we'll check to see if
the fish has found food before displaying the "I'm hungry"
thought bubble.
>> Now, running the program again, we see that the fish
doesn't get interrupted with thoughts of hunger when the
cheesy puffs are out.
The final problem we have is that the cheesy puffs don't go
away after the fish, quote unquote, "eats" them.
From the fish scripts, there's no easy way to hide the cheesy
puffs, so we need to send a message to the cheesy puffs
sprite to hide itself.
We could do this with another variable that the cheesy puffs
sprite has access to, as well as the fish sprite.
>> However, there's a cleaner way to do this in this case,
since instead of sending a message to a script that's
somewhere in the middle of executing, we can send the
message to a script that's waiting to start.
We do this by having the fish broadcast an event, one we'll
call eaten.
Then, we'll create a script for the cheesy puffs that will
wait for this event.
This is similar to the Space Bar event, except that this
time, the user's not the one directly triggering the event.
Now all we have to do is set our foodFound variable back
to false, and we can now give the hungry fish as many
servings of cheesy puffs as it wants.
>> So not too bad, right?
In C, writing multi-threaded programs is more complicated,
but the basics are the same.
Anyway, I hope you have a great time building some fun
concurrent programs in Scratch.
My name is Nate Hardison.
This is CS50.