머리말모태신앙으로 태어난 저는 고등학교 졸업하기 전까지 하나님만 알 고 있는 학생 이였습니다. 그때에는 하나님만 믿고 의지하고 기도하면서 신앙 생활하면, 내가 원하는 대학이자, 부모님의 희망인 대학으로 진학 할 거라는 확신을 가지고 있었습니다. 그러나 수학능력 시험에서 좌절하고, 재수까지 하면서 다시 본 수학능력 시험에서 다시 고배를 마시면서, 내가 믿고 있는 것에 대해서 강한 후회와 불신을 하게 되었습니다. 그때부터 비기독교 주의적 사고방식이 자리를 잡은 뒤 몇 가지 의문? 들을 혼자 만들고 의문에 답도 혼자 만들고 하여 하나님의 존재여무 자체를 부정해 오고 있습니다. 아래는 몇 가지 의문입니다.1. 1785년(?)쯤 한국으로 들어온 기독교, 그전에는 하나님을 모르는 한국인들, 모두 지옥 갔다. 보지도 듣지도 못한 사람들이 단지, 믿지 않았다는 이유 하나로, 지옥 갔다.2. 지금이 순간까지 세계 곳곳으로 뻗어 나가는 기독교, 그렇다면, 아직까지 복음이 전파 되지 않은 지역 사람들은 그냥 죽는다면, 지옥 간다.3. 산모의 약한 체질 때문에 태어나자마자 죽는 아기, 이제 세상에 나왔건만, 믿지 않았다는 이유로 지옥 간다.4. 목사님들의 비기독교적인 모습. 그들이 말하는 사랑과, 믿음은 어디 갔나?5. 기독교, 결국 종교이고, 종교라는 것이 스스로 존재하는 것이기 보다, 연약한 인간들에 의해 만들어진 소산물인거 아닌가?교회를 아니 하나님을 배반하면서 마음먹었던 것이. “내 기본적인 의문들에 대한 합리적인 답을 찾기 전까지 다시는 두 손을 안 모은다.” 이렇게 삐뚤어지기 시작하여, 28살까지 왔습니다. 그러다가, 강제? 로 기독교와 세계문화라는 과목을 수강하게 되었습니다. 당연히 학점을 떠나, 수업시간에 들려오는 기독교, 하나님, 교회, 사랑, 유일신 등의 단어들 각각은 총알이 되어서 제 맘을 뒤집어 놓기도 하고, 점점 더 멀어지는 것을 느끼었습니다.사실, 지금까지도 기독교를 생각한다는 것 자체가 괴롭고, 힘들고, 정말 하기 싫습니다. 그러나 이렇게 독후감에 앞서서 머리말부터 쓰는 이유는 작은 생각이 머릿속에 잡혀서 시작을 하려고 합니다.제가 위의 연유로 수업시간을 소홀히 하였습니다. 의도적이기도 하고, 자연스럽게 그러하기도 하였습니다. 그러다가, 어느 날 수업시간에 앉아 있다가, 문득 떠오르는 질문이 몇 주 전 수업 내용 이였습니다. “사막에 PDA가 떨어져 있으면,,,,,,” 아마 이 질문을 처음 들었을 때는 학기 초였으나, 2달쯤 지나서, 인간이 PDA보다 정교하고, 우주가 PDA보다 정교한데, 인간은 왜 살아 있나? 우주는 왜? 어떻게 돌아가나? 라는 것 이였습니다. 물론 그때의 스스로의 답은 “있나? 뭔가? 있나?”이번학기가 마지막 과제 “침묵(엔도 슈사꾸)” 독후감을 앞에 두고, 정말 많이 망설였습니다. 학점보다 중요한 것이 내 소신이고, 내 믿음인데, 학점에 의해서 독후감을 쓸 수는 없다고 생각했습니다. 또한 하나님, 교회, 사랑의 단어를 보고 싶지 않았습니다.그러다가 “사막에 PDA”가 생각나서 혹시 라는 생각으로 읽기를 마음먹었습니다.그래서 독후감을 쓰면서 독후감이라는 보다 Chapter별 느낀 점을 적으려고 합니다. 그렇게 하다보면, 혹시 하고 제 생각이 바뀔까 라는 작은 의구심을 가지고 시작하겠습니다.작은 소망은 책을 다 읽고 제 느낌 점을 스스로 읽었을 때 무엇인가 스스로 바뀐 생각이 있었으면 하는 것이 소망입니다.본론.첫머리 이야기.초기 우리나라와 비슷한 기독교 탄압. 존재하지 않는 않을 수도 있는 것(기독교)에 대한 목숨 배팅. 나라면 무엇을 위해서 그렇게 할 수 있을까?1.하나님 나라를 위해 목숨을 건 “마르타”, 말라리아에 걸려 목숨을건 소망이 좌절. 자신의 욕심을 위한 것도 아닌데, 하나님이 존재한다면, 왜 그에게 말라리아를 주었을까?2.하나님 자신의 복음을 전파하기 위해 일본으로 향하는 사제들을 왜 바다 위에서 죽도록 놔두었나?3.뭐 때문에 큰 경험도 없이 어부들은 숨어서까지 믿나?4.왜, 책속에서는 기찌지로의 질문에 대한 대답이 없을까? “무엇 때문에 이런 고통을 하나님은 주시는지요?”로드리꼬 사제 조차 극한 상황에서 이런 생각을 하는데 “만일 하나님이 안 계시다면…….” 그도 인간이기에 허용되는 건가? 물론 행동은 없었지만, 성서를 밞는 것과 마찬가지로 기독교배교는 아닌가? 사제인데…….5.“자신이 많은 순교자들이나 예수 그리스도처럼 비극적이고 영웅적이 아닌 데에 환멸가지 느꼈다.” 무엇 때문에 일본으로 갔는데, 영웅적이지 못하다고 해서 환멸을 느낄까? 하나님을 위해서 일을 한 것이지 세상 사람의 영웅이 되기 위해서 일본으로 간건 아닐 텐데…….“나는 카프랄과는 다르오.” 하나님의 사제가 왜 서로 다르다고 스스로 말하는 것일까?“하나님에게 진정으로 자비심이 있다면 무엇 때문에 천국에 이르기까지 많은 고난과 어려운 일을 부여한다고 생각하시오?” 사제에게 하는 이 질문은 내가 항상 원하는 답의 질문이었다. 이 질문의 사제의 대답은 “만약 인간이 하나님의 규칙을 그대로 실행하면 평안하게 지낼 수 잇을 것입니다.” 이 말을 내 입장에서 해석해보면, 하나님의 규칙을 그대로 실행할 수 있는 자는 과연 누구인가? 앞에서 본 사제 조차도 그러하지 못하고, 목사님들도 못하는 거 아닌가? 그렇다고 모두가 힘들게 사는 것도 아니고……. 생각하기 어려운 부분인거 같습니다. 사실 앞으로도 어떻게 생각해야 할지 모르겠습니다.“가라 가서 너희가 이룰 일을 이루어라” 이 말은 그리스도조차 용서가 아닌 분노의 말을 던진 것이라니, 왜 용서가 아닌 분노인가? 끝까지 용서와 사랑이 기독교 아닌가?6.“당신은 언제까지나 침묵을 지키셨지만, 당신은 언제까지나 침묵하실 수는 없을 것이다.” 언제? 언제????마른고기. 이것이 세상의 유혹인데 나는 과연 종교를 떠나서 세상의 유혹에 어떻게 대처하면서 살아 왔을까 생각 해 보았습니다.“성화를 제가 즐거워서 밟았다고 생각하십니까? 밟은 이 발은 아픕니다. 아파요. 나를 약한 자로 태어나게 하시고, 강한 자 흉내를 내라고 하나님은 말씀하십니다. 그건 무리라고 생각하지 않습니까?” 지금의 제 마음을 표현한 것 같습니다. 기독교를 떠났지만, 즐거워서 떠난 것이 아니고, 떠난 마음이 아픈 것도 제 마음인 거 같습니다. 강한 자 흉내를 내라는 하나님의 말씀이 있는지 없는지는 모르겠습니다만, 기독교인은 강한자 이어야 한다고 생각합니다.“그렇지만 십년 전에 태어났다면 선량한 가톨릭 신도로서 천국에 갔을지도 모릅니다.” 모든 사람이 한날한시에 한곳에서 태어나는 것을 불가능하겠지만, 적어도 그 불가능으로 인한 고통이나, 하나님의 사랑의 차별이 있어서는 안될꺼 같은데, 기찌지로의 독백은 하나님은 그럴 수 있으니 그것은 너에 대한 하나님의 계시라고 생각이 됩니다. 하지만, 이러한 점이 제가 기독교를 등지고 있는 이유 중 하나입니다. 기독교는 사랑인데, 차별적사랑?“한 인간이 무참히 죽었는데도 외계는 전혀 그런 일이 없었던 것처럼 전과 다름없이 계속 움직이고 있는 것이다. 이런 바보스러운 일은 있을 수 없다. 이것이 순교란 말인가. 무슨 의미가 있단 말인가? 왜 당신은 침묵하고 있는가. 당신은 지금 저 애꾸눈 농민이 오로지 당신 때문에 죽었다는 사실, 그것을 알고 계실 것이다. 그런데도 어째서 이런 정적이, 이런 고요가 계속 되는가.” 이 책의 제목이자, 내용 중에서 계속 되는 침묵, 아직까지 침묵이 무었을 뜻하는지 모르겠습니다. 또한, 누굴 위한 순교인가? 사제는 인간에 대한 아닌 세상에 대한 순교를 말하는 것인가 같습니다. 만약 진정으로 하나님을 믿는다면, (존재한다면,)그를 위한 순교가 세상에 영향 미치지 않는 것은 당연한 것이고, 하나님이 가슴 아파 하실 것입니다. 그런데, 왜? 침묵을.7.“한 사람의 남자에게 추녀의 깊은 정은 참기 어려운 무거운 짐이며, 석녀는 시집 갈 자격이 없다는 점 말이오.”“안이해진 육체는 그만큼 고통에 약한 법이다.”“쓸모없는 몸으로 허송세월을 보내며 옥사에서 일생을 마치느냐? 아니면 표면적으로 배교해서 인간을 위해 봉사하나, 둘 중 하나요.” 기독교 안에서의 봉사와, 기독교 밖에서의 봉사 과연 어떠한 차이가 있는가?8.왜 아니 어떻게 사제는 고문하는 순간까지 간 것일까? 그토록 침묵을 원망하고, 많은 죽음을 눈앞에서 보기도하고, 스승의 이성적인 권유에도 불구하고 고문하는 순간까지 갔을까? 모두가 만류하는 일본행, 죽음을 담보로 건너간 일본, 계속되는 하나님의 침묵 속에서 하나님에 대한 원망에도 불구하고 마지막 고문까지 갈수 있었던 건 무엇일까? 혹시 주님에 대한 믿음이 아니라, 간간히 보이는 인간의 채면, 신념 때문은 아닐까?“오늘 밤 너는 반드시 배교할 것이다.” 무엇 때문에 하나님은 사제에게 예수님과 같은 길을 걷게 하셨을까?“기도는 결코 그 고통을 덜어 주지는 못해.”, “저 사람들은 지상에서의 고통 대신에 영원한 기쁨을 얻을 수 있겠지요” “자네가 배교하겠다고 말하면 저 사람들은 구덩이에서 나올 수가 있어. 고통에서 구원받는 거지. 그런데도 자네는 배교하려고 하지 않고 있어. 자네는 그들을 위해 교회를 배반하는 일이 두렵기 때문이야.”“확실히 그리스도는 그들을 위해 배교했을 것이다.” 정말 예수가 같은 상황 이였다면, 배교를 했을까? 만약 했다면 오늘날의 기독교는 존재 했을까?“지금까지 누구도 하지 않았던 가장 괴로운 사랑의 행의를 하는 거야.” 과연 하나님의 사랑과 인간의 사랑은 다른 것인가? 누굴 위해서 사랑해야 하는가?“밟아도 좋다. 네발의 아픔을 내가 제일 잘 알고 있다. 밟아도 좋다. 나는 너희들에게 밟히기 위해 이 세상에 태어났고, 너희들의 아픔을 나누기 위해 십자가를 짊어진 것이다.” 이 말은 기독교 성경책스러운 말인거 같습니다. 그러한 말이 배교하도록 설득시키기도 하는 것은 무엇일까? 결국 하나님을 버리고, 세상의 사랑을 위해서 배교한 것인데, 이 사제는 천국을 들어 갈 수 있을까? 또한 이렇게 배교 할 것이면, 일본으로 가지 말 것이지.
condition variable를 이용한 producer-consumer 프로그램소스 작성 / 주석.{#include #include #include #include // pthread라이브 러리.#define buffer_size 10// 버퍼의 크기를 정의함.pthread_mutex_t job_mutex; // mutex(mutex_lock)를 초기화 시킴.pthread_cond_t thread_cond; // condition valued(buff_space)를 초기화 시킴.int buffer[buffer_size]; // 버퍼로 사용을 위한 int형 배열선언.int count = 0; // 버퍼의 용량을 나타내기 위한 count선언/초기화.int in = -1, out = -1; // 버퍼의 입력과 출력을 위한 in,out선언.void *producer(void *unused) { // producer함수 정의.int i,s;for (i=0;i송신 완료, buffer=1[ 0data] 수신->수신 완료, buffer=0[ 1data] 송신->송신 완료, buffer=1[ 1data] 수신->수신 완료, buffer=0[ 2data] 송신->송신 완료, buffer=1[ 2data] 수신->수신 완료, buffer=0buffer is empty{[ 3data] 송신->송신 완료, buffer=1[ 3data] 수신->수신 완료, buffer=0buffer is empty[ 4data] 송신->송신 완료, buffer=1[ 4data] 수신->수신 완료, buffer=0[ 5data] 송신->송신 완료, buffer=1[ 6data] 송신->송신 완료, buffer=2[ 5data] 수신->수신 완료, buffer=1[ 6data] 수신->수신 완료, buffer=0[ 7data] 송신->송신 완료, buffer=1[ 8data] 송신->송신 완료, buffer=2[ 7data] 수신->수신 완료, buffer=1[ 8data] 수신->수신 완료, buface신호를 기다리면서 블럭된다.) consumer는 pthread_mutex_lock (& mutex_lock) 부분에서 블록 되어 unlock되기를 기다린다. 임계영역 처리후 임계역역을 unlock시키며 (이순간도 consumer는 wait명령에 의해서 블럭된 상태임) pthread_cond_signal(&buff_space)를 실 행하여 buff_space를 기다리며 블럭된 consumer를 깨워준다. 동시에 임계영역으로 들어간다. producer는 sleep(s)후 임계영역으로 진입하려 하나 consumer가 lock시킨 상태이므로 producer은 블럭된다. consuemr는 버퍼로 부터 데이터를 출력후 unlock을 시키며 (이 순간 producer는 깨워 지며 thread는 진행된다.) 이러한 방법으로 producer은 버퍼에 입력을 consumer는 버퍼로 부터의 출 력을 진행한다.producer 부분에서 count == buffer_size일 경우는 버퍼가 꽉찬 경우 이므로 버퍼에 데이터 입력을 막기 위해서 pthread_cond_wait(&buff_space, &mutex_lock)하여 mutex를 풀고 buff_space를 기다 리면서 블록시킨다.consumer 부분에서 count == 0 일 경우는 버퍼가 비였을 경우 이므로 버퍼의 출력을 막기 위해서 pthread_cond_wait(&buff_space,&mutex_lock) 하여 mutex를 풀고 buff_space를 기다리면서 블럭시킨 다.count == buffer_size일 경우와 count == 0 일 경우 thread의 진행을 막기 위해서 같은 명령 pthread_cond_wait(&buff_space, &mutex_lock)를 사용하는데 이를 깨우기 위한 명령도 producer, consumer 마지막 부분에 있는 같은 명령인 pthread_cond_signal(&buff_space)이다. 이는 count == buffer_size일 경우와 count == 0 일 경우가 동시변수를 0으로 바꾸 었는데, 2번째 변수를 0으로 바꾸기 전에 다른 thread가 변수를 모두 1로 바꾸어 버릴수 있을것이다. 그리고 나서 다시 첫번째 thread가 두번째 변수를 0으로 바꾸게 되면, 첫번째 변수는 1이지만 두번째 변수는 0이 되는 데이타 불일치 상황이 발생하게 된다.mutex : 위의 상황을 해결하기 위해서 사용되며, pthread라이브러리에서 제공한다. mutex는 다음 3가 지 사항을 보증해 줌으로써 thread가 공유되는 메모리를 충돌없이 사용할수 있는 것이다.. atomicity : mutex_lock는 atomic operation으로 작동한다. 한번에 하나의 mutex_lock을 보증함.. singularity : 만약 thread가 mutex_lock을 했다면, 잠금을 한 thread가 mutex_unlock를 하기 전까지 다른 어떠 한 thread도 mutex잠금을 할수 없도록 보증해준다.. Non-busy wait : 하나의 thread가 mutex_lock을 시도하는데 이미 다른 thread가 mutex_lock을 사용하고 있다 면 이 thread는 다른 thread가 mutex_unlock를 하기 전까지 해당 지점에 머물러 있으며 이 동안은 어떠한 CPU자원도 소비하지 않는다.(sleep상태임.). 명령어·pthread_mutex_t mutex_lock = PTHREAD_MUTEX_INITIALIZER;// mutex_lock를 생성하고 초기화 시킴.·pthread_mutex_lock(&mutex_lock);// mutex_lock 시작함. 만약 다른 곳에서 먼저 mutex_lock을 시작하면 unlock시까지 블럭된다.·pthread_mutex_unlock(&mutex_lock);// mutex_lock을 해제 시킴.·pthread_mutex_destroy(&mutex_lock);// 생성한 mutex를 파괴함. 단, 모든mutex가 unlock되어 있어야함.. 비고 : mutex_lock을 이용한 데이터 동기화는 어디ion value를 파괴함.3가지 프로그램의 장단점 분석.(Java synchronization, semaphore,condition variable)3개의 프로그램 모두 각각의 방법은 다르지만, 동기화를 구현했다는 점에서는 서로 일맥상통하는데, 우 선 첫 번째 java 프로그램에서는 동기화를 위해서 java에서 지원하고 있는 synchronized 키워드를 사용했 는데, 이는 producer와 consumer사이의 공유버퍼 공간에서 데이터를 공유하는 여러 쓰레드들이 쓰레드 간의 충돌을 방지해 공유자원에 대한 일관성을 유지하기 위한 방법으로 사용하였다. 이 방법은 synchronized가 첨가된 메소드인 P()나 V()를 도착했을 경우 이 P(), V()메소드를 사용하고 있는 클래스는 자바 가상머신(JVM)에게 lock을 신청하고, JVM에서 승인이 나면 P() 또는 V()를 사용하고 있는 클래스 영 역을 실행하고, 실행하고 있는 동안에는 lock이 걸려 있는 상태이기에 쓰레드 모니터를 사용하여 다른 쓰 레드가 접근하는 것을 통제하게 된다. java의 synchronized방법은 약간의 성능저하가 생기는데, 다른 시스 템이 수행되는 동안 기다려야 한다는 점에서 무한정 기다릴 수 밖에 없는 starvation이 생길 수 있고, 접 근하는 시간이 같아 함께 들어오려고 하는 deadlock이 생길수 있다는 단점을 안고 있다.두 번째 프로그램에서는 Pthread 라이브러리 중 Semaphore를 사용한 방법인데, 세마포는 3번째 프로 그램에서 사용한 condition value와 같이 임계영역 문제를 해결하기 위한 동기 전용도구이다. Semaphore 는 자체적으로 mutex가 보장된다는 점에서 세 번째 프로그램과 차별화되는데, condition value는 별도의 mutex를 사용해야 블록을 지정할 수 있는 반면에 semaphore에서는 wait()와 post()만으로 블록을 걸고, 푸는 것이 가능하다. 하지만 이러한 일련의 과정이 atomic(끊어지지 않고 연속되로 인해서 절대로 동시에 두개의 프로세스가 wait()를 호출하는 것을 원천적으로 봉쇄하고 있기 때문에 절대로 두개의 프로세스가 동시에 임계영역에서 공유변수를 접근하는 일이 일어날 수 없다는 점에서 동기화 방법 중에서 신뢰도가 높다고 할 수 있다. 하지만 이러한 Semaphore에서도 문 제점은 있는데 이는 busy waiting이다. 자신의 영역으로 들어가기 전에 세마포의 값을 확인하게 되고 이 값이 0보다 작게 되는 경우 프로그램상의 루프에서 아무일도 안하고 대기하고 있게 되는 상황이 되는데, 이런 프로세스가 수천내지 수만개에 이른다면 귀중한 CPU 클럭을 소비하는 프로세스는 아무런 일도 하 지 않고 post()신호가 떨어질때까지 기다리게 되는 busy waiting이 일어날 수 있다.마지막으로 Pthread라이브러리 중 condition value를 이용한 방법에서는 mutex가 lock을 이용한 소극 적인 동기화를 제공한다면, condition value에서는 signal()과 wait()를 통한 좀더 적극적이고 세밀한 동기 화 방법을 제공한다. condition은 반드시 mutex_lock를 사용해 다른 프로세스의 진입을 막는다는 점에서 Semaphore와 구별된다. 세마포의 경우는 empty와 full변수를 wait와 함께 사용해 lock의 기능을 수행할 수 있지만, condition value의 경우에는 mutex_lock를 우선적으로 사용해 원천적으로 다른 쓰레드의 진입 을 막는다. 그 방법은 하나의 thread가 mutex_lock을 시도하는데 이미 다른 thread가 mutex_lock을 사용 하고 있다면 이 thread는 다른 thread가 mutex_unlock를 하기 전까지 해당 지점에 머물러 있게 되며, 이 동안에는 어떠한 CPU자원도 소비하지 않는다. condition value가 Semaphore와 구별되는 또 하나는 wait 의 사용에서도 볼 수 있는데, Semaphore에서는 sem_wait(&b_full)에서처럼 b_empty니다.
semaphore를 이용한 producer-consumer 프로그램소스 작성 / 주석.{#include #include #include #include // pthread라이브 러리.#include // semaphore라이브 러리.#define buffer_size 10 // 버퍼의 크기를 정의함.pthread_mutex_t mutex_lock = PTHREAD_MUTEX_INITIALIZER; // mutex(mutex_lock)를 초기화 시킴.sem_t b_full, b_empty; // semaphore 변수 b_full, b_empty 선언.int buffer[buffer_size]; // 버퍼로 사용을 위한 int형 배열선언.int count = 0; // 버퍼의 용량을 나타내기 위한 count선언/초기화.int in = -1, out = -1; // 버퍼의 입력과 출력을 위한 in,out선언.void *producer(void *unused) { // producer함수 정의.int i,s;for (i=0;i송신 완료, buffer=1[ 0data]수신->수신 완료, buffer=0buffer is empty[ 1data]송신->송신 완료, buffer=1[ 1data]수신->수신 완료, buffer=0buffer is empty[ 2data]송신->송신 완료, buffer=1[ 2data]수신->수신 완료, buffer=0buffer is empty[ 3data]송신->송신 완료, buffer=1[ 3data]수신->수신 완료, buffer=0buffer is empty[ 4data]송신->송신 완료, buffer=1[ 4data]수신->수신 완료, buffer=0buffer is empty[ 5data]송신->송신 완료, buffer=1[ 6data]송신->송신 완료, buffer=2[ 5data]수신->수신 완료, buffer=1[ 6data]수신->수신 완료, buffer=0buffer is empty[ 7data]송신->송신 완료, buf -1이 된다. 그리고 바로 pthread_mutex_lock(&mutex_lock)을 실행시켜 임계영역 부분인 (mutex_lock)을 시작하게 된다. lock이 된면 다른 producer가 실행되는 동안 consumer는 접근하지 못하게 통제된다. 버퍼에 값을 실제 집어넣는 작업은 buffer[in]=i 이부분에서 일어나는데, 우선 i를 버퍼 in번째에 입력시키고, 버퍼의 위치를 다음으로 이동시켜준다. 그리고 마지막으로 카운트 값을 증 가시켜 버퍼에 데이터를 저장하였으므로 데이터 갯수를 증가시켜 준다. 이때 만약 버퍼에 가득 찬다면 화면에 "Buffer is Full"을 출력하고, pthread_mutex_unlock(&mutex_lock)을 사용해 임계영역 (mutex_lock)의 lock를 해제시켜주며, 마지막으로 sem_post(&b_full)에서 b_empty 세마포값을 1증가 시킴으로 해서 다음 producer동작이 일어날 수 있도록 했다. consumer thread는 전체적으로 producer와 비슷한 알고리즘 형태를 가지고 있는데, 먼저 sem_wait(&b_full)를 사용해 b_empty세마 포값을 1감소 시키면서 다른 thread가 접근하려고 한다면, 세마포 값이 0이므로 해당 thread가 블럭되 도록 했고, pthread_mutex_lock (&mutex_lock)에서는 임계영역(mutex_lock)을 시작시켜 동시 접근이 있을시 mutex의 통제로 인해서 접근을 막는다. consumer에서는 버퍼에 있는 값을 소비하기 때문에 우선 data=buffer[out]를 사용해 버퍼out번째 데이터를 data에 저장함으로서 값을 사용했으며, out이 버퍼의 다음 출력될 위치를 가지고 있게 했고, 마지막으로 카운터 값을 감소시켜 버퍼의 내용 하나를 출력하였으므로 데이터 갯수를 감소시켜 주었다. 그리고 만약 count값이 0일 경우 버퍼가 비여있다는 "Buffer is empty"메시지를 화면에 뿌려준다. 현재 다른 쓰레드의 접근이 통제된 상태블럭이 되기 때문이다. (b_full세마포는 2진 세마 포임.)세마포 함수 : 세마포아(Semaphore)는 임계영역 문제를 해결하기 위하여 동기전용 도구이다. 세마포어는 크게 0과 1값사이만을 가질수 있는 바이너리(binary) 세마포어와 임의의 정수값을 가질수 있는 카운팅(counting) 세마포어로 그 종류를 나눌수 있다. 세마포 어 S는 정수값의 변수이고 초기화 과정을 제외하고 이 정수값은 시피유 내에서 3단 계에 걸친 업데이트가 아닌 아토믹하게 업데이트되는 특별한 변수이다. 또한 이 정수 값은 단 2개의 함수로 만이 조작이 가능한데 그것은 각각 wait(S)와 signal(S)이다. 두 함수의 가장 큰 특징은 각각 아토믹하게 실행 된다는 사실이다. 세마포어 S는 반 드시 한번에 한가지 함수만을 실행시킬수 있는 상호배타성, 즉 condition value는 별 도의 뮤텍스를 사용해야 하는데 반해, 세마포어 자체에서 뮤텍스가 보장된다는 것이 다. wait(S)를 어떤 프로세스가 실행하고 있는 순간에 다른 프로세스가 wait(S)는 물 론이고, signal(S)또한 절대로 실행을 할 수 가 없다는 것이다. 처리되는 방식은 제일 먼저 mutex값을 1로 초기화를 시키고, 임의의 프로세스가 자신의 임계영역에 돌입하 기 위하여 wait(mutex)를 호출하면 다른 프로세스가 이미 임계영역에 들어가 있다면, mutex값은 이미 0이 되어있는바, while루프를 맴돌며 mutex가 1로 돌아오기를 기다 리는것 외에는 아무것도 취할수 있는 행동이 안된다. 바로 문앞에서 블럭되는 경우 이다. 이미 임계영역에 들어있던 프로세스는 나오면서 반드시 signal(mutex)를 호출 하고, 이순간 mutex값은 다시 1로 되돌아 온다. 고로 while루프 안에서 뺑이돌던 프 로세스가 이번에는 while문에서 벗어나 자신의 임계영역으로 돌입하게 되는 것이다. 세마포어라는 특수성으로 인해 절대로 동시에 두 프로세스가 wait(mutex)를 호출하 는것이 원천봉쇄 되느니 만큼, 절대에서 대기중이던 프로세스 한개를 골라서 CPU에 넘겨준다. signal()은 역 으로 레디큐에 잡혀들어간 프로세스를 다시 깨워주는 역활을 한다.라이브러리 설명semaphore : condition value처럼 또하나의 동기화를 위한 방법이다.. 명령어· sem_init(&b_full,0,0); // 세마포 b_full값을 세번째 파라미터로 세마포의 갯수를 초기화('0') 시키고, 두번째 파라미터는 '0'이상을 유닉스에서 지원하니 않기 때문에 0으로 지정한다.· sem_destroy(&b_full); //세마포 b_full을 종료시킴.· sem_wait(&b_full); // b_full세마포값을 1감소 시키면서, (2진세마포의 경우) 다른 thread가 뒤늦게 진 입시 세마포 값이 0이므로 해당 thread블럭됨.· sem_post(&b_full); // b_full 세마포값을 1증가 시킨다.3가지 프로그램의 장단점 분석.(Java synchronization, semaphore,condition variable)3개의 프로그램 모두 각각의 방법은 다르지만, 동기화를 구현했다는 점에서는 서로 일맥상통하는데, 우 선 첫 번째 java 프로그램에서는 동기화를 위해서 java에서 지원하고 있는 synchronized 키워드를 사용했 는데, 이는 producer와 consumer사이의 공유버퍼 공간에서 데이터를 공유하는 여러 쓰레드들이 쓰레드 간의 충돌을 방지해 공유자원에 대한 일관성을 유지하기 위한 방법으로 사용하였다. 이 방법은 synchronized가 첨가된 메소드인 P()나 V()를 도착했을 경우 이 P(), V()메소드를 사용하고 있는 클래스는 자바 가상머신(JVM)에게 lock을 신청하고, JVM에서 승인이 나면 P() 또는 V()를 사용하고 있는 클래스 영 역을 실행하고, 실행하고 있는 동안에는 lock이 걸려 있는 상태이기에 쓰레드 모니터를 사용하여 다른 쓰 레드가 접근하는 것을 통제하게 된다. java의 synchronized방법은 약간의 성능저하가리 조의 프로그램의 경우 0과 1의 2진세마 포가 아닌 consumer에서 buffer_size까지 허용하고 있기 때문에 만약에 생길 수도 있는 deadlock을 mutex를 사용해 제어하고 있다. 자원을 사용한 후에는 자원을 내놓아 자기가 가져다 쓰기위해 S값을 1만 큼 감소시켜준다. post()신호는 임계영역에 들어있던 프로세스는 S값을 1증가시키므로 해서 쓰고 난 자원 을 반납시켜 준다. Semaphore는 여러개의 CPU가 있을 때 사용하는 방법으로서 만약 하나의 CPU에서 사용한다면 CPU를 누군가 독점하는 상황이 발생하기 때문에 무한루프가 돌게 된다. 세마포 방법은 Semaphore의 특수성으로 인해서 절대로 동시에 두개의 프로세스가 wait()를 호출하는 것을 원천적으로 봉쇄하고 있기 때문에 절대로 두개의 프로세스가 동시에 임계영역에서 공유변수를 접근하는 일이 일어날 수 없다는 점에서 동기화 방법 중에서 신뢰도가 높다고 할 수 있다. 하지만 이러한 Semaphore에서도 문 제점은 있는데 이는 busy waiting이다. 자신의 영역으로 들어가기 전에 세마포의 값을 확인하게 되고 이 값이 0보다 작게 되는 경우 프로그램상의 루프에서 아무일도 안하고 대기하고 있게 되는 상황이 되는데, 이런 프로세스가 수천내지 수만개에 이른다면 귀중한 CPU 클럭을 소비하는 프로세스는 아무런 일도 하 지 않고 post()신호가 떨어질때까지 기다리게 되는 busy waiting이 일어날 수 있다.마지막으로 Pthread라이브러리 중 condition value를 이용한 방법에서는 mutex가 lock을 이용한 소극 적인 동기화를 제공한다면, condition value에서는 signal()과 wait()를 통한 좀더 적극적이고 세밀한 동기 화 방법을 제공한다. condition은 반드시 mutex_lock를 사용해 다른 프로세스의 진입을 막는다는 점에서 Semaphore와 구별된다. 세마포의 경우는 empty와 full변수를 wait와 함께 사용해 lock의 기능을 수다.
3가지 프로그램의 장단점 분석. (Java synchronization, semaphore,condition variable) 3개의 프로그램 모두 각각의 방법은 다르지만, 동기화를 구현했다는 점에서는 서로 일맥상통하는데, 우선 첫 번째 java 프로그램에서는 동기화를 위해서 java에서 지원하고 있는 synchronized 키워드를 사용했는데, 이는 producer와 consumer사이의 공유버퍼 공간에서 데이터를 공유하는 여러 쓰레드들이 쓰레드 간의 충돌을 방지해 공유자원에 대한 일관성을 유지하기 위한 방법으로 사용하였다. 이 방법은 synchronized가 첨가된 메소드인 P()나 V()를 도착했을 경우 이 P(), V()메소드를 사용하고 있는 클래스는 자바 가상머신(JVM)에게 lock을 신청하고, JVM에서 승인이 나면 P() 또는 V()를 사용하고 있는 클래스 영역을 실행하고, 실행하고 있는 동안에는 lock이 걸려 있는 상태이기에 쓰레드 모니터를 사용하여 다른 쓰레드가 접근하는 것을 통제하게 된다. java의 synchronized방법은 약간의 성능저하가 생기는데, 다른 시스템이 수행되는 동안 기다려야 한다는 점에서 무한정 기다릴 수 밖에 없는 starvation이 생길 수 있고, 접근하는 시간이 같아 함께 들어오려고 하는 deadlock이 생길수 있다는 단점을 안고 있다.
A l t e r a4bit ALU학과 :학번 :이름 :제출날짜 :ALU (Arithmetic Logic Unit)란 : 중앙처리장치의 일부로서 컴퓨터 명령어 내에 있는 연산자들에 대해 연산과 논리동작을 담당한다. 몇몇 프로세서들에서는 ALU가 연산장치(AU)와 논리장치(LU)의 두 부분으로 나뉘어져있는 경우도 있다. 또, 어떤 프로세서들은 1 개 이상의 AU가 장착된 경우도 있는데, 예를 들어 고정 소숫점 연산을 위한 것과 부동 소숫점 연산을 위한 전용 AU를 별도로 두는 경우이다 (PC의 부동 소숫점 연산은 별도로 분리된 칩에 있는 부동 소숫점 처리장치(floating-point unit)에서 행해지는 경우도 있는데, 이것을 수치연산 보조 프로세서(numeric coprocessor)라고 부른다). 대체로 ALU는 입력과 출력을 위해 프로세서와 메인 메모리 그리고 입출력 장치에 직접 액세스를 하는데, 입력과 출력은 버스라고 부르는 전자적인 통로를 따라 흐르게 된다. 입력은 연산코드(때로 이것을 줄여서 "op code"라고 부른다)을 포함하고 있는 기계 명령어, 하나 또는 그 이상의 연산자 그리고 형식코드로 구성된다. 연산코드는 수행해야 할 연산이 무엇인지를 ALU에게 알려주며, 연산자는 그 연산을 위해 사용된다(예를 들어 두 개의 연산자를 서로 더하거나 논리적으로 비교하라는 연산일수도 있다). 형식코드는 연산코드와 함께 결합되어, 연산의 대상이 고정 소숫점 형식인지, 부동 소숫점 형식인지를 알려준다. 출력은 레지스터 내에 있는 결과와, 수행된 연산이 성공적이었는지에 관한 상태를 알려주는 값들로 구성된다. 일반적으로 ALU는 입력된 연산자와, 현재 더해지고 있는 연산자, 누산기에 저장된 결과, 그리고 시프트된 결과들을 저장하기 위한 공간을 가지고 있다. ALU 내의 비트의 흐름과, 그 안에서 수행된 연산들은 게이트 회로에 의해 통제되는데, 게이트 회로는 다시 각 연산코드에 대해 특별한 알고리즘이나 순서를 사용하는 순차 논리 장치(sequence logic unit)에 의해 통제된다. 연산장치 내에서 곱셈이나 나눗셈은 일련의 덧셈이나 뺄셈 그리고 자릿수를 이동하는 방법(shift) 등을 통해 이루어지며, 음수를 표현하는 방법에도 여러 가지가 있다. 논리장치 내에서는 16개의 논리 연산중 하나가 수행될 수 있는데, 예를 들어 두 개의 연산자를 비교해서 서로 맞지 않는 비트가 어떤 것인지를 찾아내는 것 등이 그것이다. ALU의 설계는 분명히 프로세서의 중요한 부분으로서, 명령어를 좀더 신속하게 다루기 위한 새로운 접근방식이 지속적으로 개발되고 있다.4비트 ALU 기능표와 심볼선택출력기능S1S0산술연산00F = A +B덧셈01F = A - B뺄셈논리연산10F = A BXOR11F = A BAND기능표ALU4 bitA4 bitBS1F4 bitS0심볼동작설명 : 입력 A와 B는 각각 4비트로 되어있고, 출력 F도 4비트이다. 입력에 대한 모드선택은 입력S1이 산술연산과 논리연산을 구별하며, S0는 특정한 산술 및 논리연산 동작을 생성한다.4비트 ALU 회로의 VHDL 표현Process 문이기 때문에 순차적으로 처리한다.Library ieee;use ieee.std_logic_1164.all; -- 라이브러리 패키지use ieee.std_logic_unsigned.all; -- 산술연산을 사용하기 위한 패키지Entity alu_4 is -- entity 선언port ( S : in std_logic_vector(0 to 1);-- 입력포트 S 선언, 자료형 vector(bit 객체의 배열)a,b : in std_logic_vector(0 to 3);-- 입력포트 a,b 선언, 자료형 vector(bit 객체의 배열)f : out std_logic_vector(0 to 3));-- 출력포트 F 선언, 자료형 vector(bit 객체의 배열)end alu_4; -- entity 끝architecture alu of alu_4 is -- architecture 몸체begin -- architecture 시작process(s, a, b) -- a,b,s 값이 변화하면 end process까지 처리한다.