There's a lot more to acquiring a lock than a simple CPU instruction. The cost of trying to acquire it and not getting it is very high. Documented to be somewhere between 2000 and 10,000 machine instructions. The higher number for thread context switches to a thread in another process, that requires reloading the virtual memory page translation tables.
A very common strategy that makes sense on multi-core CPUs is a spin-wait. The code goes into a tight loop, burning CPU cycles heavily, trying to acquire the lock. The exact amount of time it spends in this loop is technically a tunable item, but doesn't make much difference in practice.
Anyhoo, it is the job of the CLR and the compiler is to hide the implementation details. One core class that does this is the Monitor class. It is used when you use the lock statement in C# for example, the compiler automatically translates that to a Monitor.Enter call, auto-generating a try and finally block, the finally block executes the Leave() method.
The implementation of these methods is in the CLR. There's a fairly good chunk of code there, another thing it does is dealing with a "fairness". Which makes sure that threads cannot starve, trying to acquire the lock. That code is written in C++, still pretty far removed from raw CPU instructions. It ultimately boils down to the actual code that implements the actual lock. Yes, that's written in assembly, at least in the shared source version of the CLR. That code lives in the PAL (Platform Adapter Layer), the x86 version of it looks like this:
FASTCALL_FUNC CompareExchangeMP,12
_ASSERT_ALIGNED_4_X86 ecx
mov eax, [esp+4] ; Comparand
lock cmpxchg [ecx], edx
retn 4 ; result in EAX
FASTCALL_ENDFUNC CompareExchangeMP
The cmpxchng CPU instruction with the lock prefix is the typical one to implement locks. Your xadd is covered too though, used for Interlocked.Add:
FASTCALL_FUNC ExchangeAddUP,8
_ASSERT_ALIGNED_4_X86 ecx
xadd [ecx], edx ; Add Value to Target
mov eax, edx
retn
FASTCALL_ENDFUNC ExchangeAddUP
But that isn't typically used for locks. If you want to see this for yourself, download the SSCLI20 source code and have a look-see at clr\src\wm\i386\asmhelpers.asm. Whether that is actually used in the currently shipping version of the CLR is an open question. It's pretty core, so somewhat likely. The Monitor method implementations are in clr\vm\syncblk.cpp, AwareLock class. I'm pretty sure that the SSCLI20 version of it is not what's running on your machine, they've been tinkering with the "fairness" algorithm.