# ĐỒNG BỘ

## <mark style="color:blue;">**Bài toán tiến trình Sản xuất – Tiêu thụ**</mark>

Chương trình C minh họa bài toán bằng giải pháp Semaphore

```
#include <pthread.h>
#include <semaphore.h>
#include <stdlib.h>
#include <stdio.h>

#define MaxItems 5      // Số items tối đa một tiến trình Producer có thể tạo hoặc một tiến trình Consumer có thể dùng
#define BufferSize 3    // Kích thước bộ đệm

sem_t empty;    //Biến kiểm soát số ô nhớ trống
sem_t full;     //Biến kiểm soát số ô nhớ đầy
int in = 0;     //Biến hoạt động của tiến trình Producer
int out = 0;    //Biến hoạt động của tiến trình Consumer
int buffer[BufferSize]; //Mảng ô nhớ
pthread_mutex_t mutex;  //Khóa kiểm soát tranh chấp

//Tiến trình Sản xuất (Producer)
void *producer(void *prod)
{   
    int i, item;
    for(i = 0; i < MaxItems; i++) {
        item = rand(); // Tạo ngẫu nhiên 1 mục
        sem_wait(&empty);   //Giảm số ô nhớ trống
        pthread_mutex_lock(&mutex); //Báo hiệu vào vùng tranh chấp
        buffer[in] = item;  //thêm mục vào ô nhớ
        printf("Tiến trình Producer %d: thêm mục %d vào ô nhớ %d\n", *((int *)prod),buffer[in],in);
        in = (in+1)%BufferSize; //Trỏ đến ô nhớ kế tiếp
        pthread_mutex_unlock(&mutex);   //Ra khỏi vùng tranh chấp
        sem_post(&full);    //Tăng số ô nhớ đầy
    }
}

//Tiến trình tiêu thụ (Consumer)
void *consumer(void *cons)
{   
    int i;
    for(i = 0; i < MaxItems; i++) {
        sem_wait(&full);    //Giảm số ô nhớ đầy
        pthread_mutex_lock(&mutex); //Báo hiệu vào vùng tranh chấp
        int item = buffer[out]; //Lấy thông tin từ ô nhớ
        printf("Tiến trình Consumer %d: lấy mục %d ra khỏi ô nhớ %d\n",*((int *)cons),item, out);
        out = (out+1)%BufferSize;   //Trỏ đến ô nhớ kế tiếp
        pthread_mutex_unlock(&mutex);   //Ra khỏi vùng tranh chấp
        sem_post(&empty);   //Tăng số ô nhớ trống
    }
}


int main()
{   

    pthread_t pro[5],con[5];
    pthread_mutex_init(&mutex, NULL);
    sem_init(&empty,0,BufferSize);
    sem_init(&full,0,0);
    int i;

    int a[5] = {1,2,3,4,5};     //Số thứ tự của tiến trình Sản xuất, Tiêu thụ

    for(i = 0; i < 5; i++) {
        pthread_create(&pro[i], NULL, (void *)producer, (void *)&a[i]);
    }
    for(i = 0; i < 5; i++) {
        pthread_create(&con[i], NULL, (void *)consumer, (void *)&a[i]);
    }

    for(i = 0; i < 5; i++) {
        pthread_join(pro[i], NULL);
    }
    for(i = 0; i < 5; i++) {
        pthread_join(con[i], NULL);
    }

    pthread_mutex_destroy(&mutex);
    sem_destroy(&empty);
    sem_destroy(&full);

    return 0;
    
}
```

Kết quả biên dịch chương trình bằng GCC trên môi trường hệ điều hành CentOS

![](/files/U16l7bj3fgjneGzT57WD)

Lưu ý khi biên dịch phải liên kết thư viện tiểu trình: ***gcc tên\_chương\_trình.c –lpthread –o tên\_file\_chạy***

## <mark style="color:blue;">Bài toán bữa ăn tối của các Triết gia</mark>

Chương trình C minh họa bài toán bằng giải pháp Semaphore

```
#include<stdio.h>
#include<stdlib.h>
#include<pthread.h>
#include<semaphore.h>
#include<unistd.h>

sem_t quyen;
sem_t dua[5];

void * trietgiaantoi(void *);
void an(int);
int main()
{
	int i,a[5];
	pthread_t tid[5];

	sem_init(&quyen,0,4); //khởi tạo semaphore quyen

	for(i=0;i<5;i++)
		sem_init(&dua[i],0,1); //khởi tạo semaphore dua

	for(i=0;i<5;i++){
		a[i]=i+1;
		pthread_create(&tid[i],NULL,trietgiaantoi,(void *)&a[i]); //Tạo tiểu trình
	}
	for(i=0;i<5;i++)
		pthread_join(tid[i],NULL);  //Nối tiểu trình
}

void * trietgiaantoi(void * num)
{
	int trietgia=*(int *)num;

	sem_wait(&quyen);   //Yêu cầu quyền cầm đủ đũa
	printf("\nTriết gia %d có quyền cầm một đôi đũa",trietgia);
	sem_wait(&dua[trietgia]);   //Có chiếc đũa thứ nhất
	sem_wait(&dua[(trietgia+1)%5]); //Có chiếc đũa thứ hai

	an(trietgia);   //Ăn
	sleep(2);   //Dừng tiến trình 2 giây
	printf("\nTriết gia %d ăn xong",trietgia);

	sem_post(&dua[(trietgia+1)%5]); //Trả chiếc đũa thứ hai
	sem_post(&dua[trietgia]);   //Trả chiếc đũa thứ nhất
	sem_post(&quyen);   //Trao quyền lại cho triết gia khác
}

void an(int trietgia)
{
	printf("\nTriết gia %d đang ăn",trietgia);
}
```

Kết quả biên dịch chương trình bằng GCC trên môi trường hệ điều hành CentOS

![](/files/KUDgonowolvOBiTxMupn)


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://minilessons.gitbook.io/lessons/thuc-hanh-he-dieu-hanh/dong-bo.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
