[英]Bubble sort algorithm using Semaphores
我的任務是創建適當的信號量,並相應地使用signal
和wait
命令以使排序正常進行。 我得到了以下基本代碼
Bubble.cpp
#include <iostream>
#include <sched.h>
#include <time.h>
#include <pthread.h>
#include "sem.h"
#define NUM_CELLS 32
using namespace std;
extern sim_semaphore create_sim_sem(int) ;
extern void wait_sem (sim_semaphore) ;
extern void signal_sem (sim_semaphore) ;
/* When debugging, we need to use this lock to get
intelligible printouts of what the various threads are
doing. Warning: Don't change how this is done.
If you insist on changing it, you need to have
thought a WHOLE lot about the consequences. */
pthread_mutex_t stdoutLock ;
/* Here declare whatever semaphores, flags, counters, and
so forth, that you want to use for synchronization. Variables
declared here will be visible to (shared by) all
the threads in the task. */
/* This is the array that will be filled and then sorted by
a group of child threads. */
int cell[NUM_CELLS] ;
/* These are global variable to represent threads created dynamically. */
pthread_t thr[NUM_CELLS] ;
/* This is included to facilitate adding random delays in the code -- as a
debugging aid. */
extern long random(void);
/* This can be changed to 1, but diagnostic output will probably
seem excessive. */
int checking = 0 ;
/* A data type - a struct with an int field to represent a thread ID. */
struct threadIdType
{
int id ;
};
/* ################################################## */
/* init */
/* ################################################## */
void init()
{
/* This code initializes special lock for screen output.
Just leave this alone. */
if ( 0!=pthread_mutex_init(&stdoutLock, NULL) )
{ cout << "MUTEX INITIALIZATION FAILURE!" << endl ;
exit(-1) ;}
/* Here insert the code you want to intialize semaphores, flags, counters,
and so forth. */
/* This initializes a random number generator */
srandom(time((time_t *) 0));
}
/* ################################################## */
/* child */
/* ################################################## */
void * child(void * idPtr)
{
int m_delay, j ;
/* This is just a change of data type for convenience.
Now 'me' is the number of the child. Children have
numbers from 1 to 31=NUM_CELLS-1. */
int me = ((threadIdType *) (idPtr))->id, temp ;
do
{
/* Put entry code below here. */
/* This next segment of code is 'critical' because TWO child threads
can access most of the cells. */
if (cell[me-1] > cell[me])
{
/* Start the swap of the cell values. */
temp = cell[me-1] ;
cell[me-1] = cell[me] ;
/* I inserted delay code here below to magnify the chances
that child threads will interfere with each other.
It's a "stress test" -- if the synchronization code
the student puts in the program is good, the delays
won't cause incorrect results. On the other hand,
if the student's code is flawed, the delay code below may
increase the likelihood that the program will output
incorrect results. Leave this here. */
m_delay = (int) random()%100 ;
for (j=0; j<m_delay; j++) sched_yield();
/* Finish up with the swap. */
cell[me] = temp ;
}
/* Put exit code below here. */
} while (true) ;
pthread_exit ((void *)0) ;
}
/* ################################################## */
/* mother */
/* ################################################## */
/* The mother spawns a given number of children and then waits
for them all to finish. */
void mother()
{
int i;
/* This is a pointer to a struct that contains an int
field - it is a convenient data type to use as the
parameter to the child function. */
threadIdType * idPtr ;
for (i = 1; i < NUM_CELLS ; i++)
{
/* Mother forks a child and detaches it - she will
not join it. In other words, she will not block,
waiting for it to exit. */
idPtr = new threadIdType ;
/* This records the current index as this child's ID */
idPtr->id = i ;
/* The call below is what actually creates the child
thread and passes a pointer to the struct 'idPtr' as
the parameter to the child function. */
if ( 0!=pthread_create(&thr[i], NULL, child, (void *) idPtr) )
{ cout << "THREAD CREATION FAILURE!" << endl ;
exit(-1) ; }
if (0!=pthread_detach(thr[i]))
{ cout << "THREAD DETACHMENT FAILURE!" << endl ;
exit(-1) ;}
}
bool sorted ;
int m_delay, j;
/* The code below can be used to check to see if the
list is sorted. However, you can't leave it just as it
is. When the mother checks the condition
cell[i-1] > cell[i]
she is accessing memory that she shares with
one or two of the child threads, and the child threads
could be writing that memory concurrently, so you need to
add entry and exit code that synchronizes the
mother with the children.
You can try to think of an algorithm different from the
one below, if you want. It's possible for
the child processes to figure out collectively
whether the list is sorted. */
do
{
/* You can insert random delays like the
one below where you want - to vary
timing. */
/*
m_delay = (int) random()%100 ;
for (j=0; j<m_delay; j++) sched_yield();
*/
/* MOTHER WALKS UP THE ARRAY, CHECKING */
sorted = true ;
/* You may need to add some entry code here. */
for (i=1; i<NUM_CELLS; i++)
{
/* You may need to add some entry code here. */
if (cell[i-1] > cell[i]) sorted = false ;
/* You may need to add some exit code here. */
}
/* You may need to add some exit code here. */
} while (!sorted) ;
/* This code prints the array - which should be sorted now. */
for (i=0; i<NUM_CELLS; i++) cout << cell[i] << endl ;
}
/* ################################################## */
/* main */
/* ################################################## */
int main()
{
/* This calls the function that performs initializations. */
init();
int idx ;
/* Read the (unsorted) input into the array */
for (idx=0; idx<NUM_CELLS; idx++) cin >> cell[idx] ;
/* Echo the (unsorted) input to the screen. */
for (idx=0; idx<NUM_CELLS; idx++) cout << cell[idx]
<< endl ;
cout << endl ;
/* Execute the mother() function, which creates the
child threads that sort the list. */
mother();
return 0 ;
}
之前我曾對信號量進行過一些工作,但對於該概念我還是很陌生,可能需要更多指導。
我需要創建全局信號量變量,我之前已經做過類似的事情,例如:
sim_semaphore empty[i] ;
sim_semaphore full[i] ;
我可以再次使用相同的邏輯嗎? 意思是當一個單元格有一個值(aka已滿)並被交換時,我會相應地使用signal / wait命令嗎? 我可以僅使用兩個不同的信號量解決此問題嗎?
接下來,我將不得不在init()
內部對其進行init()
,這是我最后一次使用for循環,例如:
for (index=0; index<numTrivets; index++) full[index] = create_sim_sem(0) ;
這是再次執行此操作的最有效方法嗎?
最后,在上面說我需要輸入和退出代碼的地方,我考慮過使用Peterson的解決方案,方法是初始化boolean flag
並將首次通過設置flag = 1
,並在完成時返回flag = 0
。 但是,我已經相信這不是嘗試解決此程序的“最正確”方法。 我該怎么辦呢?
感謝所有為幫助我付出時間的人! 如果您有任何疑問或需要澄清的地方,請不要猶豫問我,我會盡力使此操作更容易幫助我。
我從這里的上一個程序中提取示例: 索引到信號量數組
我引用了彼得森的解決方案,可以在這里找到: http : //mathbits.com/MathBits/CompSci/Arrays/Bubble.htm
要回答我的問題,解決方案比我想象的要容易。 一開始我只需要一排信號燈,
sim_semaphore semArray[NUM_CELLS] ;
然后按照我的問題進行初始化。
for (index=0; index<NUM_CELLS; index++) semArray[index] = create_sim_sem(1) ;
孩子的工作僅由signal
和wait
,目標是能夠一次交換所有數據而不必一次等待。 您可以通過讓孩子在實際交換算法發生之前等待i-1
和i
並在算法之后在i-1
和i
上發信號來做到這一點。
母親的工作實質上是走數據線,並仔細檢查孩子是否完成了工作。 您可以通過在已實現的for-loop
for-loop
之前和之后創建一個for-loop
來實現此目的。 之后,您所需要做的就是在i
上wait
,然后在i
上signal
。 盡管這只是一個解決方案,但還有更復雜的解決方案,但這可能是最簡單的。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.