SO:Inkrementacje
Z Wiki Rafał (ert16) Trójniak
Spis treści |
Opis
Programy uruchamiają się w dwóch wątkach. Każdy z nich inkrementuje zmienną globalną 1000 razy. W przypadku braku synchronizacji występuje problem wyścigu, i obliczenia są niepoprawne.
1.cpp
Program do synchronizacji używa semaforów
2.cpp
Program do synchronizacji używa posixowe mutexy
Kod
1.cpp
#include <iostream> #include <pthread.h> #include <string.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <errno.h> #include <ctype.h> #include <sys/shm.h> #include <sys/sem.h> using namespace std; // Zmienna którą będziemy inkrementować int sum=0; struct sembuf lock,unlock; int semid; void ipc_lock(void) { if(semop(semid,&lock,1)) { perror("semop"); exit(-1); } } void ipc_unlock(void) { if(semop(semid,&unlock,1)) { perror("semop"); exit(-1); } } void ipc_init(void) { /* Inicjalizacja komend */ unlock.sem_num=0; unlock.sem_op = 1; unlock.sem_flg= 0; lock.sem_num=0; lock.sem_op = -1; lock.sem_flg= 0; key_t key; key = ftok("1.cpp", 'R'); if ( key==-1){ perror("ftok"); exit(1); } semid = semget(key, 0, 0); if(semid==-1) { printf("Tworzę semafor\n"); semid = semget(key, 1, 0660 | IPC_CREAT); if(semop(semid,&unlock,1)) { printf("errno:%u\n",errno); perror("semop"); exit(0); } } printf("SemId : %u\n",semid); } void ipc_destroy(void ) { /* Usuwam semafor */ if (semctl(semid, 0, IPC_RMID) == -1) { perror("semctl"); exit(1); } } // Funkcja wątku , wypisuje znak wskazywany jako argument static void * thread_start(void *arg) { for(int i=0;i<10000;i++){ ipc_lock(); sum+=2; ipc_unlock(); } return NULL; } int main(int argc, char *argv[]) { pthread_attr_t attr; pthread_t * threads; ipc_init(); // Ilość uruchamianych wątków unsigned thread_cnt = 2; threads = new pthread_t[thread_cnt ]; // Inicjalizacja wątków pthread_attr_init(&attr); for(unsigned i=0;i<thread_cnt ;i++) { // Startujemy wątki pthread_create(&(threads[i]), &attr, &thread_start, NULL); } pthread_attr_destroy(&attr); // Czekamy na zakończenia wątków for(unsigned i=0;i<thread_cnt ;i++) pthread_join(threads[i], NULL); // Aby ładnie wyglądało na konsoli cout << endl; cout << "Sum="<<sum<<endl; ipc_destroy(); }
2.cpp
#include <iostream> #include <pthread.h> #include <string.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <errno.h> #include <ctype.h> using namespace std; // Zmienna którą będziemy inkrementować int sum=0; static pthread_mutex_t mux; void ipc_lock() { pthread_mutex_lock(&mux); } void ipc_unlock() { pthread_mutex_unlock(&mux); } void ipc_init() { // Inicjalizacja mutexa if(pthread_mutex_init(&mux, NULL)) { perror("pthread_mutex_init"); exit(-1); } } // Funkcja wątku , wypisuje znak wskazywany jako argument static void * thread_start(void *arg) { for(int i=0;i<10000;i++){ ipc_lock(); sum+=2; ipc_unlock(); } return NULL; } int main(int argc, char *argv[]) { pthread_attr_t attr; pthread_t * threads; ipc_init(); // Ilość uruchamianych wątków unsigned thread_cnt = 2; threads = new pthread_t[thread_cnt ]; // Inicjalizacja wątków pthread_attr_init(&attr); for(unsigned i=0;i<thread_cnt ;i++) { // Startujemy wątki pthread_create(&(threads[i]), &attr, &thread_start, NULL); } pthread_attr_destroy(&attr); // Czekamy na zakończenia wątków for(unsigned i=0;i<thread_cnt ;i++) pthread_join(threads[i], NULL); // Aby ładnie wyglądało na konsoli cout << endl; cout << "Sum="<<sum<<endl; }