All objects automatically contain a single lock (also referred to as a monitor). When you call
any synchronized method, that object is locked and no other synchronized method of
that object can be called until the first one finishes and releases the lock. For the preceding
methods, if f( ) is called for an object by one task, a different task cannot call f( ) or g( ) for
the same object until f( ) is completed and releases the lock. Thus, there is a single lock that
is shared by all the synchronized methods of a particular object, and this lock can be used
to prevent object memory from being written by more than one task at a time.
Note that it’s especially important to make fields private when working with concurrency;
otherwise the synchronized keyword cannot prevent another task from accessing a field
directly, and thus producing collisions.