如果写者拥有优先权,用ReentrantReadWriteLock似乎不好实现,昨晚就用汇编语言写了个,程序输出结果到打开的.txt问题格式如:
01348 R 672 47
01520 R 766 16
01656 W 828 63
01800 R 907 0
第一项表示线程ID,第二项表示操作属性,第三项表示延迟时间,第四项表示操作时间,都是用Sleep函数来模拟
源程序如下:
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;writer and reader problem
.386
.model flat, stdcall
option casemap:none
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;include文件定义
include windows.inc
include user32.inc
includelib user32.lib
include kernel32.inc
includelib kernel32.lib
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;equ等值定义
DLG_MAIN equ 1000
ICO_MAIN equ 100
IDC_READER equ 1001
IDC_WRITER equ 1002
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;数据段
.data
dwWriter dd 5 ;写者数量
dwReader dd 30 ;读者数量
dwWriterNumber dd 0 ;当前正在写的数量
dwReaderNumber dd 0 ;当前正在读的数量
dwOption dd 1
szReaderMessage db '%05d R %6d %6d', 0dh, 0
szWriterMessage db '%05d W %6d %6d', 0dh, 0
.data?
hInstance dd ?
hReader dd ?
hWriter dd ?
hStart dd ?
hWSemaphore dd ? ;控制写的信号量
hWriterNumber dd ? ;控制修改dwWriterNumber的信号量
hRSemaphore dd ? ;读线程排队的信号量
hRSem dd ? ;当至少有一个写线程时,禁止所有的读线程
hReaderNumber dd ? ;控制修改dwReaderNumber的信号量
.const
szWriter db '写操作',0
szReader db '读操作',0
szDestClass db 'Notepad',0
szStop db '退出',0
szNotFound db '没有找到文本窗口',0
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;代码段
.code
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;将运行结果在记事本窗口中显示
_SendtoNotepad proc _lpsz
local @hDest
pushad
invoke FindWindow,addr szDestClass,NULL
.if eax
mov ecx,eax
invoke ChildWindowFromPoint,ecx,20,20
.endif
.if eax
mov @hDest,eax
mov esi,_lpsz
@@:
lodsb
or al,al
jz @F
movzx eax,al
invoke PostMessage,@hDest,WM_CHAR,eax,1
jmp @B
@@:
.endif
popad
ret
_SendtoNotepad endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;Readter过程
_ProcReader proc _lparam
local @dwThreadID
local @dwTickCounter1
local @dwTickCounter2
local @szBuffer[20]:byte
pushad
invoke GetTickCount ;获取系统时间
mov @dwTickCounter1, eax
invoke GetCurrentThreadId ;获取当前线程ID
mov @dwThreadID, eax
mov ecx, 2
xor edx, edx
div ecx
invoke Sleep,eax
invoke GetTickCount ;得到延迟时间
sub eax, @dwTickCounter1
mov @dwTickCounter2, eax
invoke WaitForSingleObject, hRSemaphore, INFINITE
invoke WaitForSingleObject, hRSem, INFINITE
invoke WaitForSingleObject, hReaderNumber, INFINITE
inc dwReaderNumber
.if dwReaderNumber==1
invoke WaitForSingleObject, hWSemaphore, INFINITE
.endif
invoke ReleaseSemaphore, hReaderNumber, 1, NULL
invoke ReleaseSemaphore, hRSem, 1, NULL
invoke ReleaseSemaphore, hRSemaphore, 1, NULL
mov eax, @dwThreadID
mov ecx, 100
xor edx, edx
div ecx
invoke Sleep, edx ;在这里呆一会
invoke WaitForSingleObject, hReaderNumber, INFINITE
dec dwReaderNumber
.if dwReaderNumber == 0
invoke ReleaseSemaphore, hWSemaphore, 1, NULL
.endif
invoke ReleaseSemaphore, hReaderNumber, 1, NULL
invoke GetTickCount ;得到操作时间
sub eax, @dwTickCounter1
sub eax, @dwTickCounter2
mov @dwTickCounter1, eax
invoke wsprintf, addr @szBuffer, addr szReaderMessage,/
@dwThreadID, @dwTickCounter2, @dwTickCounter1
invoke _SendtoNotepad, addr @szBuffer
popad
ret
_ProcReader endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;Writer过程
_ProcWriter proc _lparam
local @dwThreadID
local @dwTickCounter1
local @dwTickCounter2
local @szBuffer[20]:Byte
pushad
invoke GetTickCount
mov @dwTickCounter1, eax
invoke GetCurrentThreadId ;获取当前线程ID
mov @dwThreadID, eax
.if (eax&4)
invoke Sleep, eax
.else
mov ecx, 2
xor edx, edx
div ecx
invoke Sleep, eax
.endif
invoke WaitForSingleObject, hWriterNumber, INFINITE
inc dwWriterNumber
.if dwWriterNumber == 1
invoke WaitForSingleObject, hRSem, INFINITE
.endif
invoke ReleaseSemaphore, hWriterNumber, 1, NULL
invoke WaitForSingleObject, hWSemaphore, INFINITE
invoke GetTickCount ;得到延迟时间
sub eax, @dwTickCounter1
mov @dwTickCounter2, eax
mov eax, @dwThreadID
mov ecx, 100
xor edx, edx
div ecx
invoke Sleep, edx ;在这里呆一会
invoke ReleaseSemaphore, hWSemaphore, 1, NULL
invoke WaitForSingleObject, hWriterNumber, INFINITE
dec dwWriterNumber
.if dwWriterNumber == 0
invoke ReleaseSemaphore, hRSem, 1, NULL
.endif
invoke GetTickCount ;得到操作时间
sub eax, @dwTickCounter1
sub eax, @dwTickCounter2
mov @dwTickCounter1, eax
invoke wsprintf, addr @szBuffer, addr szWriterMessage,/
@dwThreadID, @dwTickCounter2, @dwTickCounter1
invoke _SendtoNotepad, addr @szBuffer
invoke ReleaseSemaphore, hWriterNumber, 1, NULL
popad
ret
_ProcWriter endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;对话框过程
_ProcDlgMain proc uses ebx esi edi, hWnd, wMsg, wParam, lParam
mov eax, wMsg
.if eax == WM_COMMAND
mov eax, wParam
.if ax == IDOK
.if dwOption == 1
mov dwOption, 0
invoke GetDlgItemInt, hWnd, IDC_READER,NULL, FALSE
mov dwReader, eax
invoke GetDlgItemInt, hWnd, IDC_WRITER, NULL, FALSE
mov dwWriter, eax
invoke SetWindowText, hStart, offset szStop
.while (dwWriter>0)
invoke CreateThread, NULL, NULL,offset _ProcWriter,/
NULL, NULL, NULL
dec dwWriter
.endw
.while (dwReader>0)
invoke CreateThread, NULL, NULL, offset _ProcReader,/
NULL, NULL, NULL
dec dwReader
.endw
.elseif dwOption == 0
invoke EndDialog, hWnd, NULL
.endif
.endif
.elseif eax == WM_CLOSE
invoke EndDialog, hWnd, NULL
.elseif eax == WM_INITDIALOG
invoke LoadIcon, hInstance, ICO_MAIN
invoke SendMessage, hWnd, WM_SETICON, ICON_BIG, eax
invoke GetDlgItem, hWnd, IDC_READER
mov hReader, eax
invoke GetDlgItem, hWnd, IDC_WRITER
mov hWriter, eax
invoke GetDlgItem, hWnd, IDOK
mov hStart, eax
invoke CreateSemaphore, NULL, 1, 1, NULL ;写线程信号量
mov hWSemaphore, eax
invoke CreateSemaphore, NULL, 1, 1, NULL ;控制dwNumber修改的信号量
mov hWriterNumber, eax
invoke CreateSemaphore, NULL, 1, 1, NULL ;读线程信号量
mov hRSemaphore, eax
invoke CreateSemaphore, NULL, 1, 1, NULL ;控制读线程的信号量
mov hRSem, eax
invoke CreateSemaphore, NULL, 1, 1, NULL ;控制dwReader修改的信号量
mov hReaderNumber, eax
.else
mov eax, FALSE
ret
.endif
mov eax, TRUE
ret
_ProcDlgMain endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
start:
invoke GetModuleHandle, NULL
mov hInstance,eax
invoke DialogBoxParam, eax, DLG_MAIN,/
NULL, offset _ProcDlgMain, NULL
invoke ExitProcess,NULL
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
end start
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
01348 R 672 47
01520 R 766 16
01656 W 828 63
01800 R 907 0
第一项表示线程ID,第二项表示操作属性,第三项表示延迟时间,第四项表示操作时间,都是用Sleep函数来模拟
源程序如下:
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;writer and reader problem
.386
.model flat, stdcall
option casemap:none
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;include文件定义
include windows.inc
include user32.inc
includelib user32.lib
include kernel32.inc
includelib kernel32.lib
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;equ等值定义
DLG_MAIN equ 1000
ICO_MAIN equ 100
IDC_READER equ 1001
IDC_WRITER equ 1002
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;数据段
.data
dwWriter dd 5 ;写者数量
dwReader dd 30 ;读者数量
dwWriterNumber dd 0 ;当前正在写的数量
dwReaderNumber dd 0 ;当前正在读的数量
dwOption dd 1
szReaderMessage db '%05d R %6d %6d', 0dh, 0
szWriterMessage db '%05d W %6d %6d', 0dh, 0
.data?
hInstance dd ?
hReader dd ?
hWriter dd ?
hStart dd ?
hWSemaphore dd ? ;控制写的信号量
hWriterNumber dd ? ;控制修改dwWriterNumber的信号量
hRSemaphore dd ? ;读线程排队的信号量
hRSem dd ? ;当至少有一个写线程时,禁止所有的读线程
hReaderNumber dd ? ;控制修改dwReaderNumber的信号量
.const
szWriter db '写操作',0
szReader db '读操作',0
szDestClass db 'Notepad',0
szStop db '退出',0
szNotFound db '没有找到文本窗口',0
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;代码段
.code
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;将运行结果在记事本窗口中显示
_SendtoNotepad proc _lpsz
local @hDest
pushad
invoke FindWindow,addr szDestClass,NULL
.if eax
mov ecx,eax
invoke ChildWindowFromPoint,ecx,20,20
.endif
.if eax
mov @hDest,eax
mov esi,_lpsz
@@:
lodsb
or al,al
jz @F
movzx eax,al
invoke PostMessage,@hDest,WM_CHAR,eax,1
jmp @B
@@:
.endif
popad
ret
_SendtoNotepad endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;Readter过程
_ProcReader proc _lparam
local @dwThreadID
local @dwTickCounter1
local @dwTickCounter2
local @szBuffer[20]:byte
pushad
invoke GetTickCount ;获取系统时间
mov @dwTickCounter1, eax
invoke GetCurrentThreadId ;获取当前线程ID
mov @dwThreadID, eax
mov ecx, 2
xor edx, edx
div ecx
invoke Sleep,eax
invoke GetTickCount ;得到延迟时间
sub eax, @dwTickCounter1
mov @dwTickCounter2, eax
invoke WaitForSingleObject, hRSemaphore, INFINITE
invoke WaitForSingleObject, hRSem, INFINITE
invoke WaitForSingleObject, hReaderNumber, INFINITE
inc dwReaderNumber
.if dwReaderNumber==1
invoke WaitForSingleObject, hWSemaphore, INFINITE
.endif
invoke ReleaseSemaphore, hReaderNumber, 1, NULL
invoke ReleaseSemaphore, hRSem, 1, NULL
invoke ReleaseSemaphore, hRSemaphore, 1, NULL
mov eax, @dwThreadID
mov ecx, 100
xor edx, edx
div ecx
invoke Sleep, edx ;在这里呆一会
invoke WaitForSingleObject, hReaderNumber, INFINITE
dec dwReaderNumber
.if dwReaderNumber == 0
invoke ReleaseSemaphore, hWSemaphore, 1, NULL
.endif
invoke ReleaseSemaphore, hReaderNumber, 1, NULL
invoke GetTickCount ;得到操作时间
sub eax, @dwTickCounter1
sub eax, @dwTickCounter2
mov @dwTickCounter1, eax
invoke wsprintf, addr @szBuffer, addr szReaderMessage,/
@dwThreadID, @dwTickCounter2, @dwTickCounter1
invoke _SendtoNotepad, addr @szBuffer
popad
ret
_ProcReader endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;Writer过程
_ProcWriter proc _lparam
local @dwThreadID
local @dwTickCounter1
local @dwTickCounter2
local @szBuffer[20]:Byte
pushad
invoke GetTickCount
mov @dwTickCounter1, eax
invoke GetCurrentThreadId ;获取当前线程ID
mov @dwThreadID, eax
.if (eax&4)
invoke Sleep, eax
.else
mov ecx, 2
xor edx, edx
div ecx
invoke Sleep, eax
.endif
invoke WaitForSingleObject, hWriterNumber, INFINITE
inc dwWriterNumber
.if dwWriterNumber == 1
invoke WaitForSingleObject, hRSem, INFINITE
.endif
invoke ReleaseSemaphore, hWriterNumber, 1, NULL
invoke WaitForSingleObject, hWSemaphore, INFINITE
invoke GetTickCount ;得到延迟时间
sub eax, @dwTickCounter1
mov @dwTickCounter2, eax
mov eax, @dwThreadID
mov ecx, 100
xor edx, edx
div ecx
invoke Sleep, edx ;在这里呆一会
invoke ReleaseSemaphore, hWSemaphore, 1, NULL
invoke WaitForSingleObject, hWriterNumber, INFINITE
dec dwWriterNumber
.if dwWriterNumber == 0
invoke ReleaseSemaphore, hRSem, 1, NULL
.endif
invoke GetTickCount ;得到操作时间
sub eax, @dwTickCounter1
sub eax, @dwTickCounter2
mov @dwTickCounter1, eax
invoke wsprintf, addr @szBuffer, addr szWriterMessage,/
@dwThreadID, @dwTickCounter2, @dwTickCounter1
invoke _SendtoNotepad, addr @szBuffer
invoke ReleaseSemaphore, hWriterNumber, 1, NULL
popad
ret
_ProcWriter endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;对话框过程
_ProcDlgMain proc uses ebx esi edi, hWnd, wMsg, wParam, lParam
mov eax, wMsg
.if eax == WM_COMMAND
mov eax, wParam
.if ax == IDOK
.if dwOption == 1
mov dwOption, 0
invoke GetDlgItemInt, hWnd, IDC_READER,NULL, FALSE
mov dwReader, eax
invoke GetDlgItemInt, hWnd, IDC_WRITER, NULL, FALSE
mov dwWriter, eax
invoke SetWindowText, hStart, offset szStop
.while (dwWriter>0)
invoke CreateThread, NULL, NULL,offset _ProcWriter,/
NULL, NULL, NULL
dec dwWriter
.endw
.while (dwReader>0)
invoke CreateThread, NULL, NULL, offset _ProcReader,/
NULL, NULL, NULL
dec dwReader
.endw
.elseif dwOption == 0
invoke EndDialog, hWnd, NULL
.endif
.endif
.elseif eax == WM_CLOSE
invoke EndDialog, hWnd, NULL
.elseif eax == WM_INITDIALOG
invoke LoadIcon, hInstance, ICO_MAIN
invoke SendMessage, hWnd, WM_SETICON, ICON_BIG, eax
invoke GetDlgItem, hWnd, IDC_READER
mov hReader, eax
invoke GetDlgItem, hWnd, IDC_WRITER
mov hWriter, eax
invoke GetDlgItem, hWnd, IDOK
mov hStart, eax
invoke CreateSemaphore, NULL, 1, 1, NULL ;写线程信号量
mov hWSemaphore, eax
invoke CreateSemaphore, NULL, 1, 1, NULL ;控制dwNumber修改的信号量
mov hWriterNumber, eax
invoke CreateSemaphore, NULL, 1, 1, NULL ;读线程信号量
mov hRSemaphore, eax
invoke CreateSemaphore, NULL, 1, 1, NULL ;控制读线程的信号量
mov hRSem, eax
invoke CreateSemaphore, NULL, 1, 1, NULL ;控制dwReader修改的信号量
mov hReaderNumber, eax
.else
mov eax, FALSE
ret
.endif
mov eax, TRUE
ret
_ProcDlgMain endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
start:
invoke GetModuleHandle, NULL
mov hInstance,eax
invoke DialogBoxParam, eax, DLG_MAIN,/
NULL, offset _ProcDlgMain, NULL
invoke ExitProcess,NULL
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
end start
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>