뮤텍스 질문입니다..

소맛라면의 이미지

      1 #include<stdio.h>
      2 #include<unistd.h>
      3 #include<stdlib.h>
      4 #include<string.h>
      5 #include<pthread.h>
      6 #include<semaphore.h>
      7
      8 void *thread_function(void *arg);
      9 pthread_mutex_t work_mutex;
     10
     11 #define WORK_SIZE 1024
     12 char work_area[WORK_SIZE];
     13 int  time_to_exit = 0;
     14
     15 int main(){
     16     int res;
     17     pthread_t a_thread;
     18     void *thread_result;
     19     res = pthread_mutex_init(&work_mutex,NULL);
     20     if(res != 0){
     21         perror("Mutex initialization failed");
     22         exit(EXIT_FAILURE);
     23     }
     24     res = pthread_create(&a_thread, NULL, thread_function,NULL);
     25     if(res != 0){
     26         perror("Thread creation failed");
     27         exit(EXIT_FAILURE);
     28     }
     29     pthread_mutex_lock(&work_mutex);
     30     printf("Input some text. Enter 'end' to finish\n");
     31     while(!time_to_exit){
     32         fgets(work_area, WORK_SIZE, stdin);
     33         printf("1")
     34         pthread_mutex_unlock(&work_mutex);
     35         while(1){
     36             pthread_mutex_lock(&work_mutex);
     37             if(work_area[0] != '\0'){
     38                 pthread_mutex_unlock(&work_mutex);
     39                 sleep(1);
     40             }
     41             else{
     42                 break;
     43             }
     44         }
     45     }
     46     pthread_mutex_unlock(&work_mutex);
     47     printf("\nWainting for thread to finish...\n");
     48     res = pthread_join(a_thread, &thread_result);
     49     if(res != 0){
     50         perror("Thread join failed");
     51         exit(EXIT_FAILURE);
     52     }
     53     printf("Thread join \n");
     54     pthread_mutex_destroy(&work_mutex);
     55     exit(EXIT_SUCCESS);
     56 }
     57
     58 void *thread_function(void *arg)
     59 {
     60     printf("2");
     61     sleep(1);
     62     pthread_mutex_lock(&work_mutex);
     63     while(strncmp("end",work_area, 3) != 0){
     64         printf("You input %d characters\n", strlen(work_area) -1);
     65         work_area[0] = '\0';
     66         pthread_mutex_unlock(&work_mutex);
     67         sleep(1);
     68         pthread_mutex_lock(&work_mutex);
     69         while(work_area[0] == '\0'){
     70             pthread_mutex_unlock(&work_mutex);
     71             sleep(1);
     72             pthread_mutex_lock(&work_mutex);
     73         }
     74     }
     75
     76     time_to_exit = 1;
     77     work_area[0] = '\0';
     78     pthread_mutex_unlock(&work_mutex);
     79     pthread_exit(0);
     80 }
 

[root@localhost chapter12]# ./thread4
Input some text. Enter 'end' to finish
asdf
21You input 4 characters
end
1
Wainting for thread to finish...
Thread join
[root@localhost chapter12]#

뮤텍스에 대해 잠시 보고 있습니다.
의문나는 점이 있어서 이렇게 질문을 하내요.

실행화면을 보면 숫자 1이 2뒤에 출력되는것을 볼수 있습니다.
소스를아무리 봐도 이해가 가지 않습니다
숫자 1이 먼저 출력 되야 하지 않을까요?
fgets()로 문자열을 입력 받은 후에 바로 출력 해줬는데
어찌 숫자2가 먼저 출력 될까요???

falsetru의 이미지

     60     pthread_mutex_lock(&work_mutex);
     61     printf("2");
     62     sleep(1);
익명 사용자의 이미지

쓰레드 사이에서 어떤 것이 우선권을 가질지는 스케쥴러 마음입니다.
여기서는 당연히 쓰레드가 먼저 생성되었기 때문에 2가 먼저 출력되는게 당연한것 같습니다. 메인 함수에서는 쓰레드 생성후에 몇가지 작업을 하는 반면, 쓰레드에서는 생성되자 마자 2를 출력하게 되어있으니...

mutex 보다는 condition variable을 써야 원하는 제어구조를 얻을 수 있습니다.

익명 사용자의 이미지

정상입니다.
* 왜 1이 먼저 출력되어야 한다고 생각하십니까?

소맛라면의 이미지

제 생각은 이렇습니다.

공유변수 초기화 -> 뮤택스 초기화 -> 쓰래드 생성 이 때부터 쓰레드가 2개가 되는것이죠..

메인과 새로운 쓰레드..

제 생각에도 2가 먼저 나오는것이 맞기는 맞습니다..
왜냐면 main 에서 새로운 쓰레드 생성후 fgets()함수를 호출할때까지 2개의
쓰레드 같이 실행되니까요(사실은 그렇지 않지만..)
main 이 fgets()를 실행하기 전에 숫자 2를 찍어 줘야 제가 생각하는 논리에
맞는것 같습니다..

하지만 보는바와 같이 fgets()실행 후에 숫자 2가 먼저 찍히니 이상하다는
것이죠

fgets()함수를 호출하기 전에 이미 숫자 2가 찍혀 있지만
보이지 않고 있다가. fgets()후에 보이는 것인가요???

머릿속이 복잡하군요...;;

무엇을 위해 사는가..

익명 사용자의 이미지

Quote:

...
fgets()함수를 호출하기 전에 이미 숫자 2가 찍혀 있지만
보이지 않고 있다가. fgets()후에 보이는 것인가요???
...

예.

이 문제는 아주 빈번하게 회자되는 주제군요. FAQ수준..

* 일단 concurrent programming을 수행(개발/디버깅등)할 때는 buffered io를 사용하지 않을것을 권고합니다.

* 아래를 실행해보면 되겠습니다.

실험 1) 그냥 출력함
#include <stdio.h>
main()
{
printf("1");
sleep(3); // 엥 ? 3초동안 1도 안나오네....
printf("2");
} // 읔, 프로그램 종료되니까 나오네..

실험 2) printf()의 끝부분에 \n을 추가함
#include <stdio.h>
main()
{
printf("1\n"); // 음 ... \n의 효과라...!
sleep(3);
printf("2");
}

실험 3) stdout의 라이브러리의 버퍼를 0으로 함=>버퍼링 안함
#include <stdio.h>
main()
{
setvbuf (stdout, NULL, _IONBF, 0);etvbuf (stdout, NULL, _IONBF, 0); // 버퍼를 0으로...
printf("1"); // \n 없음
sleep(3);
printf("2");
} // 이경우 printf() == write()와 거의 동급으로 사용됨, 나은점은 %d등 포맷팅이 자유롭다는..

실험 4) printf()후 매번 강제로 버퍼를 비워줌(강제출력) =>버퍼링 안함
#include <stdio.h>
main()
{
printf("1");
fflush(stdout);
sleep(3);
printf("2");
fflush(stdout);
} // 좀 귀찮나서리... 키보드치기가... 또한 atomic하지도 않고...

* 질문자는 1번과 같은 유형으로 수행해서 그러합니다.
* 운영체제 스케쥴러에 의해 다수 프로세스/쓰레드가 실제 printf()를 실행한 순서대로 출력하기 위해서는 buffered-io를 사용해서는 안됩니다.
* 저는 그래서 관습처럼 unbuffered-io를 일단 기본 IO로 사용할 것을 권고합니다.
* 효율등의 문제로 버퍼링을 하는것이 필요하다면 이는 만들어서 쓰는게 좋겠다는...
* 어쨌거나 저는 write()를 가장 선호합니다. 상위 버퍼링은 자작으로...

익명 사용자의 이미지

쿵~
아 ...오타가.... 실험3의 올바른 코드는 아래와 같습니다.

// 실험 3)
#include <stdio.h> 
main() 
{ 
   setvbuf (stdout, NULL, _IONBF, 0); // 버퍼를 0으로... 
   printf("1"); // \n 없음 
   sleep(3); 
   printf("2"); 
} // 이경우 printf() == write()와 거의 동급으로 사용됨, 나은점은 %d등 포맷팅이 자유롭다는..
소맛라면의 이미지

감사합니다...
실험해보니..그렇군요...
이러한 문제가 있었다니...
감사합니다.
손님님...

무엇을 위해 사는가..

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.