Of course, "synchronized" is just syntactic sugar - extremley useful syntactic sugar.
If you want sugar-free java programs, you should be writing directly in java byte code the monitorenter, monitorexit, lock, and unlock operations referenced in VM Specifications 8.13 Locks and Synchronization
There is a lock associated with every object. The Java programming
language does not provide a way to
perform separate lock and unlock
operations; instead, they are
implicitly performed by high-level
constructs that always arrange to pair
such operations correctly. (The Java
virtual machine, however, provides
separate monitorenter and monitorexit
instructions that implement the lock
and unlock operations.)
The synchronized statement computes a
reference to an object; it then
attempts to perform a lock operation
on that object and does not proceed
further until the lock operation has
successfully completed. (A lock
operation may be delayed because the
rules about locks can prevent the main
memory from participating until some
other thread is ready to perform one
or more unlock operations.) After the
lock operation has been performed, the
body of the synchronized statement is
executed. Normally, a compiler for the
Java programming language ensures that
the lock operation implemented by a
monitorenter instruction executed
prior to the execution of the body of
the synchronized statement is matched
by an unlock operation implemented by
a monitorexit instruction whenever the
synchronized statement completes,
whether completion is normal or
abrupt.
A synchronized method automatically
performs a lock operation when it is
invoked; its body is not executed
until the lock operation has
successfully completed. If the method
is an instance method, it locks the
lock associated with the instance for
which it was invoked (that is, the
object that will be known as this
during execution of the method's
body). If the method is static, it
locks the lock associated with the
Class object that represents the class
in which the method is defined. If
execution of the method's body is ever
completed, either normally or
abruptly, an unlock operation is
automatically performed on that same
lock.
Best practice is that if a variable is
ever to be assigned by one thread and
used or assigned by another, then all
accesses to that variable should be
enclosed in synchronized methods or
synchronized statements.
Although a compiler for the Java
programming language normally
guarantees structured use of locks
(see Section 7.14, "Synchronization"),
there is no assurance that all code
submitted to the Java virtual machine
will obey this property.
Implementations of the Java virtual
machine are permitted but not required
to enforce both of the following two
rules guaranteeing structured locking.
Let T be a thread and L be a lock.
Then:
The number of lock operations performed by T on L during a method
invocation must equal the number of
unlock operations performed by T on L
during the method invocation whether
the method invocation completes
normally or abruptly.
At no point during a method invocation may the number of unlock
operations performed by T on L since
the method invocation exceed the
number of lock operations performed by
T on L since the method invocation.
In less formal terms, during a method
invocation every unlock operation on L
must match some preceding lock
operation on L.
Note that the locking and unlocking
automatically performed by the Java
virtual machine when invoking a
synchronized method are considered to
occur during the calling method's
invocation.