# Mutex Programming

Mutex lock (<mark style="color:purple;">**MUT**</mark>ual <mark style="color:purple;">**EX**</mark>clusion lock) เป็น Semaphore อย่างง่ายที่นำมาใช้ในการจัดการ Mutual Exclusion กับทรัพยากรที่ถูกใช้งานร่วมกันได้อย่างมีประสิทธิภาพโดยเฉพาะกับ thread โดย Mutex จะเป็นตัวแปรที่มีได้ 2 สถานะ คือ สถานะปลดล็อค (`unlock`) หรือ สถานะล็อค (`lock`) ซึ่งใช้เพียง 1 บิต (1-bit) ที่แสดงสถานะของมัน แต่ในทางปฏิบัติเราใช้ตัวแปรจำนวนเต็ม (integer) โดยให้สถานะ `unlocked` เป็นเลขศูนย์ และสถานะ `lock` จะใช้เลขอื่นแทน

<figure><img src="/files/xXXb4cpFYdsHgFblsx9P" alt="" width="346"><figcaption><p><em>รูปแสดงการเข้าไปกำหนดค่าใน mutex ของเทรดที่ต้องการเข้าไปขอใช้ทรัพยากร</em> </p></figcaption></figure>

นักพัฒนาสามารถพัฒนาโปรแกรมโดยเรียกใช้ความสามารถในการจัดกลไกการทำงานประสานกันระหว่างเทรด (synchronization mechanisms) โดยไม่ให้เกิดปัญหาในกรณีที่เทรดแต่ละตัวจะต้องเข้าไปใช้ทรัพยากรตัวเดียวกัน ภายในเครื่องคอมพิวเตอร์เดียวกันโดยใช้ไลบรารี pthread ซึ่งจากรูปด้านบนแสดงการอนุญาตเพียง thread #1 ตัวเดียวที่สามารถเข้าไปกำหนดค่า mutex (Mutual Exclusion Lock) เพื่อเข้าถึงทรัพยากรหรือตัวแปร โดยที่ thread #2 จะต้องรอ (block) คิวเพื่อเข้าถึงทรัพยากรหรือตัวแปรหลังจากที่ thread #1 ทำงานเสร็จเรียบร้อยแล้ว ตัว thread #2 จึงจะสามารถเข้าไปกำหนดค่า mutex เพื่อขอเข้าถึงทรัพยากรหรือตัวแปรนั้นต่อไป

แต่อย่างไรก็ตามการใช้ mutex จะถูกใช้ได้เพียงในกรณีมีหลายเทรดในโปรเซสตัวเดียวกันเท่านั้น แต่ในกรณีที่มีหลายโปรเซสต้องการเข้าใช้ทรัพยากรเดียวกัน จะต้องแก้ไขโดยการใช้เทคนิค semaphore แทน mutex ซึ่งจะกล่าวในหัวข้อ 6.2.3 ต่อไป

<figure><img src="/files/du5R2SrnJEcOUl3Rf3nl" alt=""><figcaption></figcaption></figure>

{% hint style="info" %}
ฟังก์ชันที่เกี่ยวข้องสำหรับ <mark style="color:purple;">**mutex**</mark> ภายในไลบรารี <mark style="color:orange;">**`pthread`**</mark> ได้แก่    &#x20;

* <mark style="color:orange;">**`pthread_mutex_lock()`**</mark> ใช้สำหรับการเข้าไปล็อคค่าในตัวแปร mutex การเรียกฟังก์ชันนี้ก็จะถูกบล๊อคเอาไว้ไม่ให้เทรดอื่นเข้ามา จนกว่าเทรดตัวที่ใช้งานอยู่ทำการปล่อยตัว mutex เท่านั้น
* <mark style="color:orange;">**`pthread_mutex_unlock()`**</mark> เพื่อปล่อยหรือปลดล็อคค่า `mutex` จากเทรดที่ใช้ `mutex` อยู่
* <mark style="color:orange;">**`pthread_mutex_trylock()`**</mark> เพื่อใช้ตรวจสอบตัวแปร `mutex` ว่ากำลังถูกใช้ล๊อคใช้งานอยู่หรือไม่ ซึ่งจะมีประโยชน์ในการป้องกันไม่ให้เกิดเหตุการณ์ที่เทรดแต่ละตัวต่างฝ่ายต่างรอให้แต่ละตัวเสร็จ (deadlock conditions)
  {% endhint %}

{% hint style="success" %}

### ตัวอย่าง

{% endhint %}

ตัวอย่างแสดงการสร้างเทรดจำนวน 10 เทรด โดยแต่ละตัวจะเข้าไปใช้งานตัวแปรกลางชื่อว่า counter แต่จะต้องเพิ่มค่า counter ได้เพียงครั้งละ 1 เทรดเท่านั้น

```c
// simple_mutex.c
#include <stdio.h>
#include <pthread.h>
#define NTHREADS 10
void* thread_function(void*);
pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER;
int counter = 0;

main() {
	pthread_t thread_id[NTHREADS];
	int i, j;

	for (i = 0; i < NTHREADS; i++) {
		pthread_create(&thread_id[i], NULL, thread_function, NULL);
	}

	for (j = 0; j < NTHREADS; j++) {
		pthread_join(thread_id[j], NULL);
	}
// Now that all threads are complete I can print the final result.     
// Without the join I could be printing a value before all the threads 
// have been completed.                                                

	printf("Final counter value: %d\n", counter);
}

void* thread_function(void *dummyPtr) {
	printf("Thread number %ld\n", pthread_self());
	pthread_mutex_lock(&mutex1);
	counter++;
	pthread_mutex_unlock(&mutex1);
}
```

คอมไพล์ และทดสอบรันโปรแกรม

```shell-session
$ gcc -o simple_mutex simple_mutex.c –lpthread
$ ./simple_mutex 
Thread number 139638417069824
Thread number 139638425462528
Thread number 139638442247936
Thread number 139638433855232
Thread number 139638408677120
Thread number 139638400284416
Thread number 139638391891712
Thread number 139638383499008
Thread number 139638375106304
Thread number 139638366713600
Final counter value: 10
```


---

# 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://docs.aic-eec.com/computer-operation-systems/linux-os-dev.-engineer/process-synchronization/mutex-programming.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.
