커널 수준 스레드와 사용자 수준 스레드의 특징과 차이는 무엇인가요?
"커널 레벨 스레드란 OS에 의해 실행되는 스레드입니다. OS가 인식할 수 있어 각 스레드가 개별적으로 관리될 수 있다는 장점이 있지만 스케쥴링과 동기화를 위한 시스템 콜이 빈번하게 발생하여 오버헤드가 발생합니다.
유저 레벨 스레드란 커널이 인식하지 못하는 스레드로 프로세스 단위로 스케쥴링이 됩니다. 그렇기때문에 하나의 스레드에 시스템콜이 발생하는 경우 같은 프로세스 내의 다른 스레드들 또한 중단되어 응답성이 낮아진다는 단점이 있습니다. 하지만 컨텍스트 스위칭에서 발생하는 오버헤드가 적어 속도가 빠르다는 장점이 있습니다"
유저 모드 커널 모드랑 다름!!! 커널
모드
스레드 아니고 커널이 인식할 수 있는 커널레벨
스레드임!!
OS 및 커널에 의해 관리되는 스레드
각 스레드가 개별적으로 작업이 가능하다
프로세스 작업 효율 측면에서 커널레벨 스레드가 유저레벨보다 좋다
커널에서 더 많은 기능을 사용할 수 있어 안정성, 기능성이 좋다
유저모드에서 커널모드로의 전환(스케쥴링 및 동기화를 위한 시스템콜)이 빈번하게 발생하여 성능 저하가 발생할 수 있다
스레드간 전환시 커널모드로의 전환이 필요하다
생성이 유저레벨보다 느리다
사용자가 라이브러리를 사용해 생성하고 관리하는 스레드
커널모드로의 전환이 없기때문에 성능저하가 없다
=컨텍스트 스위칭을 프로세스 내부에서 할 수 있다
=스케쥴링과 동기화를 위한 시스템콜이 필요없다
=커널과 관계없이 스케쥴링이 가능하다
→ 커널레벨스레드보다 생성이 쉽고 빠르며 관리 또한 쉽다
어느 os에서나 운영이 가능해 이식성이 높다
커널모드에서는 유저모드 스레드가 인식되지 않기때문에 하나의 스레드에 시스템콜이 발생하면 같은 프로세스 내의 다른 스레드도 같이 작업이 불가한 상태가 된다
어플리케이션이 멀티스레드여도 멀티프로세싱의 잇점이 없다
+번외
사용자 수준의 스레드는 프로세스로 인식되어 커널 수준의 스레드 1개에 매핑된다
https://www.tutorialspoint.com/user-level-threads-and-kernel-level-threads
https://colinch4.github.io/2020-02-02/%EC%BB%A4%EB%84%90%EB%A0%88%EB%B2%A8%EC%8A%A4%EB%A0%88%EB%93%9C-vs-%EC%9C%A0%EC%A0%80%EB%A0%88%EB%B2%A8%EC%8A%A4%EB%A0%88%EB%93%9C/
교착상태란 무엇이며, 교착상태가 발생하기 위해서는 어떤 조건이 있어야 하나요?
"교착상태란 시스템 자원에 대한 요구가 뒤엉킨 상태로 교착상태의 발생 조건은 4가지가 있습니다.
상호배제란 사용중인 자원을 다른 프로세스가 사용하지 못하도록 하는 것이고, 점유대기는 이미 자원을 점유하고 있는 프로세스가 자원을 해제하지 않은 채로 다른 자원을 사용하기 위해 대기하고 있는 상태를 말합니다. 비선점은 자원을 선점할 수 없는 것을 말하고 순환대기란 점유대기가 순환적으로 발생하는 것을 말합니다. "
교착상태의 해결법은 무엇인가요?
"교착상태의 해결 방법으로는 예방, 회피, 탐지, 복구가 있습니다.
예방은 교착상태가 발생한 4가지의 조건 중 하나를 부정함으로써 교착상태를 예방하는 것이고 회피는 교착상태를 예측해서 회피하는 방법입니다. 회피 알고리즘은 오버헤드가 크다는 단점이 있습니다. 탐지는 탐지 알고리즘을 사용해서 교착상태인 프로세스를 탐지하는 것인데 알고리즘이 자주 호출되면 오버헤드가 커진다는 단점이 있습니다. 복구는 교착상태의 프로세스를 찾아 종료하는 방법입니다."
교착상태의 프로세스를 종료시키는 방법: 해당 프로세스의 자원을 선점하거나 할당된 자원을 해제한다
def solution(numbers, hand):
hand='R' if hand =='right' else 'L'
keypad=[[1,2,3],[4,5,6],[7,8,9],['*',0,'#']]
keypad_cord={}
for i in range(len(keypad)):
for j,val in enumerate(keypad[i]):
keypad_cord[val]=(i,j)
answer = ''
l='*'
r='#'
for num in numbers:
if num in [1,4,7]:
answer+='L'
l=num
elif num in [3,6,9]:
answer+='R'
r=num
else:
x,y=keypad_cord[num]
xr,yr=keypad_cord[r]
xl,yl=keypad_cord[l]
dr=abs(x-xr)+abs(y-yr)
dl=abs(x-xl)+abs(y-yl)
if dr>dl:
answer+='L'
l=num
elif dr==dl:
answer+=hand
if hand=='L':
l=num
else:
r=num
else:
answer+='R'
r=num
return answer
이 문제의 핵심은 좌표로 표현해서 거리를 비교하는 것
하지만 이때 일반적으로 생각하는 직선거리를 구하면 안되고 상하좌우로만 이동할 수 있다는 조건이 있기 때문에 유의해야한다.
일반적으로 생각하는 유클리드 거리를 적용하면 안되고 맨해튼 거리
공식을 이용해야한다
사실 맨해튼까지 가지 않아도 상하좌우로만 이동이 가능하기때문에 그냥 x좌표값의 차이의 절댓값과 y좌표값의 차의 절댓값을 더하는 게 맞다
def solution(numbers, hand):
answer = ''
location = [[3, 1], [0, 0], [0, 1], [0, 2], [1, 0], [1, 1], [1, 2], [2, 0], [2, 1], [2, 2]]
left, right = [3, 0], [3, 2]
for i in numbers:
if i % 3 == 1:
answer += 'L'
left = location[i]
elif i % 3 == 0 and i != 0:
answer += 'R'
right = location[i]
else:
l = abs(location[i][0] - left[0]) + abs(location[i][1] - left[1])
r = abs(location[i][0] - right[0]) + abs(location[i][1] - right[1])
if l < r:
answer += 'L'
left = location[i]
elif l > r:
answer += 'R'
right = location[i]
else:
answer += hand[0].upper()
if hand == 'right':
right = location[i]
else:
left = location[i]
return answer
location에 인덱스값에 해당하는 number의 위치를 저장했다
left, right는 지금 손의 위치로 *, #을 나타낸다
numbers의 요소 i에 대해서 3으로 나눈 나머지가 1이면 왼편의 숫자들 1,4,7에 해당되므로 left의 로케이션을 바꿔준다
마찬가지로 3으로 나눈 나머지가 딱 떨어질 때 0을 제외하고는 오른손 3,6,9에 해당하므로 right의 로케이션을 바꿔준다
그 외에 2,5,8,0의 번호를 누를 경우 지금 있는 위치와 왼손/ 오른손의 위치를 계산해서 가까운 손의 로케이션을 바꿔준다.
거리가 같은 경우 hand의 앞글자 r/l을 대문자로 바꾼 글자를 더해준다
나도 이렇게 하려다가 말았는데 내가 한 방식이나 이 방식이나 둘다 굳이 할 필요는 없는 것 같다 그치만 재밌단말이지..
무튼간 3으로 나눈 이 방식이 상당히 깔끔하고 좋은 것 같다
키패드의 위치가 고정되어있어서 이렇게 숫자로 접근할 생각을 못했었는데 역시 똑똑한 사람 너무 많고 좋다 오예