The core of synchronization is the monitor, which allows an object to be owned by exactly one thread. When one thread owns the monitor on an object, all other threads wishing to take control of the monitor must wait until the owning thread relinquishes control.
The monitorenter and monitorexit instructions and the synchronized method keyword are just the beginning. The class java.lang.Thread provides many other ways to take advantage of monitors. Many features of thread control have not been discussed fully here, because they are well documented at the Java level. Have a look at the documentation for java.lang.Thread and java.lang.ThreadGroup for these features. For an introduction to the topic, try The Java Programming Language, by Ken Arnold and James Gosling, which has a good introduction to threads in Java. Then read Concurrent Programming in Java, by Doug Lea. It contains many good examples of how to use threads to take advantage of concurrency in your programs.