操作系統恐龍書第十版課後答案 ch6

6.1 In Section 6.4, we mentioned that disabling interrupts frequently can affect the system’s clock. Explain why this can occur and how such effects can be minimized.

系統時鐘在每個時鐘中斷時被更新。如果中斷被禁用,特別是在較長的時間內禁用,系統時鐘可能會輕易失去正確的時間。系統時鐘也用於排程目的。例如,進程的時間片通常以時鐘滴答數表示。在每個時鐘中斷時,排程器確定當前運行的進程的時間片是否已過期。如果禁用了時鐘中斷,排程器將無法正確分配時間片。這種效應可以通過僅在非常短的時間內禁用時鐘中斷來降低。

6.2 What is the meaning of the term busy waiting? What other kinds of waiting are there in an operating system? Can busy waiting be avoided altogether? Explain your answer.

忙碌等待(Busy waiting)意味著一個進程在一個緊密的迴圈中等待條件滿足,而不釋放處理器。避免忙碌等待的一種策略是將等待中的進程暫時置於睡眠狀態,當達到適當的程式狀態時再喚醒它,但這種解決方案需要處理將進程置於睡眠狀態和稍後喚醒的開銷。

6.3 Explain why spinlocks are not appropriate for single-processor systems yet are often used in multiprocessor systems.

在單處理器系統中,自旋鎖(Spinlocks)通常不適用,因為打破自旋鎖的條件只能通過執行不同的進程來獲得。如果一個進程不釋放處理器,其他進程就不會有機會設置所需的程序狀態,使第一個進程能夠取得進展。在多處理器系統中,其他進程在其他處理器上運行,因此可以修改程序狀態以釋放第一個進程的自旋鎖。

6.4 Show that, if the wait() and signal() semaphore operations are not executed atomically, then mutual exclusion may be violated.

一個wait()操作會原子性地減少與信號量關聯的值。如果在信號量的值為1時執行了兩個wait()操作,並且這些操作不是原子操作,則兩個操作可能都會減少信號量的值,從而違反了互斥性。爲確保互斥性,等待操作必須是原子操作,以便在多個線程或進程同時嘗試等待信號量時,只有一個能成功減少信號量的值,而其他操作被阻塞。

6.5 Illustrate how a binary semaphore can be used to implement mutual exclusion among n processes.

這 n 個進程共享一個初始值為 1 的信號量 mutex。每個進程 Pi 的組織如下:

do {

           wait(mutex);

            /* critical section */

           signal(mutex);

           /* remainder section */

       } while (true);

6.6 Race conditions are possible in many computer systems. Consider a banking system that maintains an account balance with two functions: deposit(amount) and withdraw(amount). These two functions are passed the amount that is to be deposited or withdrawn from the bank account balance. Assume that a husband and wife share a bank account. Concurrently, the husband calls the withdraw() function, and the wife calls deposit(). Describe how a race condition is possible and what might be done to prevent the race condition from occurring.

假設帳戶中的餘額是250.00美元,然後丈夫呼叫withdraw(50)並且妻子呼叫deposit(100)。顯然,正確的餘額應該是300.00美元。由於這兩筆交易將被序列化,丈夫的本地餘額值變為200.00美元,但在他能夠提交交易之前,deposit(100)操作發生並更新了餘額的共享值為300.00美元。然後我們切換回丈夫,共享餘額的值被設定為200.00美元,這明顯是不正確的值。

6.7 The pseudocode of Figure 6.15 illustrates the basic push() and pop() operations of an array-based stack. Assuming that this algorithm could be used in a concurrent environment, answer the following questions:
a. What data have a race condition?
b. How could the race condition be fixed?

a. 變數top存在競爭條件。假設push()和pop()函數被同時調用。在stack[top] = item語句執行之前,pop()中的top--語句已經執行。這將導致被推送的項目替換了當前位於stack[top]位置的項目。

b. 這個競爭條件可以使用互斥鎖來解決。使用互斥鎖可以確保同一時間只有一個線程可以訪問共享資源,這樣可以避免競爭條件的出現。這樣,將在push()和pop()函數中使用互斥鎖,可以確保它們不會同時運行,從而解決競爭條件的問題。

6.8 The following program example can be used to sum the array values of size N elements in parallel on a system containing N computing cores (there is a separate processor for each array element):
for j = 1 to log 2(N) {
    for k = 1 to N {
           if ((k + 1) % pow(2,j) == 0) {
               values[k] += values[k - pow(2,(j-1))]
                                 }
                      }
           }
This has the effect of summing the elements in the array as a series of partial sums, as shown in Figure 6.16. After the code has executed, the sum of all elements in the array is stored in the last array location. Are there any race conditions in the above code example? If so, identify where they occur and illustrate with an example. If not, demonstrate why this algorithm is free from race conditions.

是的,該行存在競爭條件:

val[k] = val[k - pow(2,(j-1))] + val[k]

如果執行緒的執行變得交錯,則有可能一個執行緒在另一個執行緒完成之前已經完成了其分配的部分總和。以50為例,它包含了部分總和15和35(分別存儲在數組位置1和3)。如果15還沒有被計算,那麼部分總和50將變為10 + 35 = 45。

這種情況可以通過同步機制,如互斥鎖或其他機制,來解決,以確保不同執行緒之間的計算不會產生競爭條件,從而確保正確的計算。

6.9 One approach for using compare and swap() for implementing a spinlock is as follows:
void lock spinlock(int *lock) {
while (compare and swap(lock, 0, 1) != 0)
; /* spin */
}
A suggested alternative approach is to use the “compare and compareand-swap” idiom, which checks the status of the lock before invoking the compare and swap() operation. (The rationale behind this approach is to invoke compare and swap()only if the lock is currently available.) This strategy is shown below:
void lock spinlock(int *lock) {
{
while (true) {
if (*lock == 0) {
/* lock appears to be available */
if (!compare and swap(lock, 0, 1))
break;
}
}
}
Does this “compare and compare-and-swap” idiom work appropriately for implementing spinlocks? If so, explain. If not, illustrate how the integrity of the lock is compromised.

這種編程慣用法適當地工作。假設Thread 1正在該函數中,並且鎖(lock)的值等於0。發生上下文切換到Thread 2,Thread 2同樣進入函數。Thread 2仍然將鎖(lock)視為值為0,進入compare and swap()函數,將鎖(lock)設置為1,並返回0,這使Thread 2跳出while循環。當控制切換回Thread 1時(Thread 1仍然認為鎖(lock)等於0),它也調用compare and swap(),現在返回1(鎖的值),並繼續自旋。

這種方式可確保只有一個線程能夠成功設置鎖(lock),而其他線程將自旋等待鎖(lock)的釋放。這是一種有效的同步機制,用於實現互斥性,以防止多個線程同時訪問關鍵區域。

6.10 The first known correct software solution to the critical-section problem for two processes was developed by Dekker. The two processes, P0 and P1, share the following variables:
while (true) {
flag[i] = true;
while (flag[j]) {
if (turn == j) {
flag[i] = false;
while (turn == j)
; /* do nothing */
flag[i] = true;
}
}
/* critical section */
turn = j;
flag[i] = false;
/* remainder section */
}
The structure of process Pi (i == 0 or 1) is shown in Figure 6.18. The other process is Pj (j == 1 or 0). Prove that the algorithm satisfies all three requirements for the critical-section problem.

該算法滿足互斥性的三個條件:

  1. 互斥性:通過使用flag和turn變數來確保互斥性。如果兩個進程都將它們的flag設為true,只有一個進程能成功,即輪到哪個進程。等待的進程只有在另一個進程更新turn的值時才能進入其臨界區域。

  2. 進展性:同樣通過flag和turn變數來提供進展性。該算法不提供嚴格的輪流進入。相反,如果一個進程希望訪問其臨界區域,它可以將其flag變數設為true並進入臨界區域。它只在退出臨界區域時才將turn設置為另一個進程的值。如果該進程希望再次進入其臨界區域(在另一個進程之前),它將重複進入其臨界區域並在退出時將turn設置為另一個進程。

  3. 有界等待:通過使用TTturn變數來保持有界等待。假設兩個進程希望進入其臨界區域。它們都將它們的flag值設為true;然而,只有輪到哪個進程能繼續;另一個進程等待。如果不保持有界等待,等待的進程可能必須無限等待,而第一個進程一再進入和退出其臨界區域。然而,Dekker算法有一個過程來設置turn的值為另一個進程,從而確保另一個進程將下一個進入其臨界區域。

6.11 Consider how to implement a mutex lock using the compare and swap() instruction. Assume that the following structure defining the mutex lock is available:
typedef struct {
int available;
} lock;
The value (available == 0) indicates that the lock is available, and a value of 1 indicates that the lock is unavailable. Using this struct, illustrate how the following functions can be implemented using the compare and swap() instruction:
• void acquire(lock *mutex)
• void release(lock *mutex)
Be sure to include any initialization that may be necessary.

ANS:Figure 6.101.

6.12 Assume that a system has multiple processing cores. For each of the following scenarios, describe which is a better locking mechanism—a spinlock or a mutex lock where waiting processes sleep while waiting for the lock to become available:
• The lock is to be held for a short duration.
• The lock is to be held for a long duration.
• A thread may be put to sleep while holding the lock.

• Spinlock

• Mutex lock

• Mutex lock

6.13 A multithreaded web server wishes to keep track of the number of requests it services (known as hits). Consider the two following strategies to prevent a race condition on the variable hits. The first strategy is to use a basic mutex lock when updating hits:
int hits;
mutex lock hit lock;
hit lock.acquire();
hits++;
hit lock.release();
// initialization
mutex->available = 0;
// acquire using compare and swap()
void acquire(lock *mutex) {
while (compare and swap(&mutex->available, 0, 1) != 0)
;
return;
}
// acquire using test and set()
void acquire(lock *mutex) {
while (test and set(&mutex->available) != 0)
;
return;
}
void release(lock *mutex) {
mutex->available = 0;
return;
}
A second strategy is to use an atomic integer:
atomic t hits;
atomic inc(&hits);
Explain which of these two strategies is more efficient.

在這種情況下使用鎖是不必要的。通常情況下,鎖操作需要系統調用,並且如果鎖不可用,可能需要將進程置於睡眠狀態(進行上下文切換)。(喚醒該進程將需要另一個上下文切換。)另一方面,原子整數提供了對hits變數的原子更新,並確保hits不會出現競爭條件。這可以在不涉及內核干預的情況下完成。因此,第二種方法更有效。

6.14 Servers can be designed to limit the number of open connections. For example, a server may wish to have only N socket connections at any point in time. As soon as N connections are made, the server will not accept another incoming connection until an existing connection is released. Illustrate how semaphores can be used by a server to limit the number of concurrent connections.

信號量初始化為允許的開放套接字連接數。當接受一個連接時,調用acquire()方法;當釋放一個連接時,調用release()方法。如果系統達到允許的套接字連接數,則後續對acquire()的調用將被阻塞,直到現有連接被終止並調用release方法。這種方法可用於控制並發線程或進程對套接字連接的訪問,以確保不超出系統設定的限制。

6.15 Describe how the signal() operation associated with monitors differs from the corresponding operation defined for semaphores.

與監視器關聯的signal()操作在以下意義上不是持久的:如果執行了一個signal,並且沒有正在等待的線程,那麼signal將被忽略,系統不會記住發生了信號。如果隨後執行等待操作,則相應的線程將被阻塞。在信號量中,即使沒有正在等待的線程,每次信號都會導致信號量值相應增加。由於早先的增量,未來的等待操作將立即成功。

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值