1 16.070 Introduction to Computers and Programming 26 April Recitation 10 Spring 2001 Topics Multi-tasking (by example): • Basic multi-tasking on the workstation • Inter-thread communication • Viewing and Changing Priority Multi-tasking (by example) Basic multi-tasking /* * Multithreaded example: * * This program will let you spawn as many threads as * you like. Each thread, when spawned from main(), is * given a unique number. It will print its task number * to the screen, wait a random number of milliseconds, * then print,then wait, etc. * * * If you make the Sleep() a constant (say, 600), and * generate a small number of tasks, they will execute in * an orderly fashion. * * If you generate a large number of tasks, or open netscape * and go to shockwave.com (or do something else that * distracts the CPU), you'll start to see some chaos. * * * This program requires the multithread library. go to the * Project -> Settings -> C/C++ tab and select Category "Code Generation" * and choose "multithreaded" under the "use runtime library:" * Max number of threads is 500 unless you make some changes. */ #include <windows.h> #include <stdlib.h> #include <string.h> #include <stdio.h> #include <conio.h> #include <process.h> void MyThreadTask( void *MyID ); /* A task to be spawned */ /* multiple times */ int main() /* Task One */ { int i=0, Tasknum=0; char KeyInfo; /* Clear the screen.*/ system("cls"); printf("Generating thread... Press any key except Q to spawn a new one\n");2 /* Generate multiple tasks */ do { printf("main\n"); fflush(stdin); KeyInfo = _getch(); /* Sleep until a key is pressed */ if(KeyInfo != 'q') /* If not "q", make a new task */ { Tasknum++; _beginthread( MyThreadTask, 0, (void *)Tasknum ); /* spawn task */ } } while( KeyInfo != 'q' );/* Loop until user presses 'q' */ } void MyThreadTask( void *MyID ) { int num = (int)MyID; char space[500]; memset(space,' ',500); /* create a string of spaces */ space[num]='\0'; /* "num" long, and null-terminated */ printf(" Task %d Spawned \n", num); while(1) /* loop forever */ { Sleep( rand()%2000 ); /* sleep a while */ printf("\t%s<%d>\n",space,num); /* I'm alive! */ } } Inter-thread communication Mutex/Semaphore free Inter-thread communication (NOT DESIRABLE): When two or more threads share the same resource (e.g. a global variable), multitasking might result in undesirable resource modification. E.g. say threads A and B share resource R. A reads R and makes a decision regarding modification of R based on its reading . Then A is swapped out and thread B is swapped in. B modifies A. A now swaps back in and modifies R since it did not know of B’s modification to R. Clearly this is undesirable. #include <windows.h> #include <stdlib.h> #include <string.h> #include <stdio.h> #include <conio.h> #include <process.h> /* Each task reads the following number and adds 5 to it if it is 0 and subtracts 5 from it if it is 5 */ int Inc_Dec=0; /* Increment Decrement */ void MyThreadTask( void *MyID ); /* A task to be spawned */ /* multiple times */ int main() /* Task One */ { int i=0, Tasknum=0; char KeyInfo; /* Create mutexes */ hAvailable = CreateMutex(NULL, FALSE, NULL); /* cleared */3 /* Clear the screen.*/ system("cls"); printf("Generating thread... Press any key except Q to spawn a new one\n"); /* Generate multiple tasks */ do { printf("main\n"); fflush(stdin); KeyInfo = _getch(); /* Sleep until a key is pressed */ if(KeyInfo != 'q') /* If not "q", make a new task */ { Tasknum++; _beginthread( MyThreadTask, 0, (void *)Tasknum ); /* spawn task */ } } while( KeyInfo != 'q' ); /* Loop until user presses 'q' */ /* clean up handles */ CloseHandle(hAvailable); return 0; } Inter-task ommunication using a Mutex: Before accessing and modifyiing a shared resource (like a global variable), determine if the resource is in use by another thread by checking if a mutex associated with the resource is locked. If locked, indicate to the operating system that you would like to queue for availability and wait for availability. Once the mutex is unlocked, you have control over the resource and the operating system again locks the mutex on your behalf. If unlocked, lock mutex and modify/use resource. Unlock mutex when resource usage is complete. /* This program illustrates how a number of tasks attempt to toggle the value of Inc_Dec between 0 and 5, but fail to do so correctly, since no resource (Inc_Dec) control/auditing is done. */ #include <windows.h> #include <stdlib.h> #include <string.h> #include <stdio.h> #include <conio.h> #include <process.h> HANDLE hAvailable; /* Availability Mutex */ /* Each task reads the following number and adds 5 to it if it is 0 and subtracts 5 from it if it is 5 */ int Inc_Dec=0; /* Increment Decrement */ void MyThreadTask( void *MyID ); /* A task to be spawned */ /* multiple times */ int main() /* Task One */ { int i=0, Tasknum=0; char KeyInfo; /* Create mutexes */ hAvailable = CreateMutex(NULL, FALSE, NULL); /* cleared */ /* Clear the screen.*/ system("cls"); printf("Generating thread... Press any key except Q to spawn a new one\n"); /* Generate multiple tasks */ do {4 printf("main\n"); fflush(stdin); KeyInfo = _getch(); /* Sleep until a key is pressed */ if(KeyInfo != 'q') /* If not "q", make a new task */ { Tasknum++; _beginthread( MyThreadTask, 0, (void *)Tasknum ); /* spawn task */ } } while( KeyInfo != 'q' ); /* Loop until user presses 'q' */ /* clean up handles */ CloseHandle(hAvailable); return 0; } void MyThreadTask( void *MyID ) { int num = (int)MyID; char space[500]; int Inc_Dec_Local; memset(space,' ',500); /* create a string of spaces */ space[num]='\0'; /* "num" long, and
View Full Document