Course Links

Resources

External

This lab will give you the chance to investigate concurrency in a graphical programming language called Snap!. The activities here are based on a lab from UC Berkeley.

To get started, go to snap.berkeley.edu and click on the "Run Snap! now" button. You should see the Snap! workspace, with language blocks on the left, an area for building scripts in the middle, and a white stage (output/execution area) on the upper right.

Snap! GUI

A note for later: if you want more background on how to build programs in Snap! check out this crash course.

Exploration

Let's start with a simple program. Snap! programs are constructed out of visual blocks snapped together into finished structures. Different syntactic elements have different shapes, and fit into holes of a matching shape. The way blocks fit together is analogous to the way Backus-Naur nonterminals fit together in describing text-based languages. In fact, we could write a set of Backus-Naur rules for the Snap! language.

We won't do that now, though. Instead, we'll put together a simple program. Assemble blocks as shown below. You'll need a yellow block from the Control palette, a green block from the Operators palette, and a blue block from the Motion palette.

first Snap! program

When your program is finished, what do you see? The wedge-shaped cursor in the stage area will be rotating around its point. Our program begins to run as soon as it is assembled.

Now add a second thread to your program. This one will be like the first, except the rotation should be in the opposite direction.

second Snap! program

What happens? Each thread is running simultaneously, and they cancel each other out. To verify that both are actually working, you can toggle the true to false on either program. When you do so, the other thread is no longer opposed and will be able to turn the cursor in its desired direction.

You can add many more concurrent threads, each acting in parallel with the others. They can move the cursor, draw things, and much more. If you make the cursor move forward a bit at each step, then you can use the two turning threads to steer it. Experiment a little bit and see what other interesting things you can make happen. (I made a program that causes the cursor to move slowly towards the mouse location, like the monsters in a zombie movie.)

More Concurrency

Snap! programs can be stored in files and loaded into the workspace. Download this file to your computer, and then upload it using the file menu in the upper left: LaunchTutorial

third Snap! program

Spend some time studying the program to figure out what it does. This program doesn't begin doing anything interesting until you click the green flag button. When you do that, it begins to move the cursor, and it leaves a trace behind as it does so. There are two threads set up initially, one that moves the cursor forwards and one that turns it slightly. The end result is a circular motion. Where it gets interesting is that there's another thread that's waiting for a signal from you. When you hit space bar (or click on it), it sends a signal to the thread at the bottom. That thread in turn generates another forward-motion thread. Since all threads are acting in parallel, the total amount of forward motion per turn gets bigger, and the circle being drawn gets bigger.

The next program to look at is SerialVsParallelBuggy. Load it and let it run. Here we have three sprites working to fill in their half of the stage. The yellow sprite is working alone, but the two blue sprites work in parallel. Which side finishes faster?

You'll notice a small bug that leaves a square unfilled near the beginning. It's a bug related to the concurrency. See if you can diagnose what is happening and fix it. (Hint: remember that at every tick of the clock, each thread gets executed once in turn. If you're still not sure what's happening, carefully watch the location of the missing stamp as you click the green flag button.)

Nondeterminism

We can use a variation on the space-filling program to investigate nondeterminism. Begin with the opposite, a program called Determinism. This program has four threads all working at the same time to fill in squares on the stage. Because Snap! divides time fairly and consistently between each thread, the program always runs in the same order every time. All the threads fill each square one after the other, starting with blue and ending with white. Since white is always the last to fill a square, that is what you see after the program has run.

We can make the program nodeterministic by inserting a random delay inside the space-filling loop. This loop is stored in a custom code block called Fill Screen. Find it at the bottom of the Pen palette and right-click to open an edit window. Add the command wait (1 / (pick random [1] to [10])) secs inside the loop and click OK to save. Now run the program again and see what happens.

Each time you run it you should get a different result. Since the delay is random in each thread, they fill at different speeds in what becomes a sort of race. The final color of each square reflects the color of the thread that was in last place at that point in the race.

More Exploration

If you have finished the above and have more time, you can either explore the capabilities of Snap! or you can look at the program MultipleBroadcast. This example displays some of the counter-intuitive behavior you can get with multiple interacting threads. The "go" message should cause an increment to each of five numbers in a list. The 'w' and 'b' keys each cause three "go" messages to be sent. Do they both behave as you expect? Try checking the "Thread safe scripts" checkbox under the gear menu. Does this change the result? Is it what you expect? Can you come up with a menchanism to explain the observed behavior?