Sometime prior to JDK 1.4 synchronization caused some pretty hefty performance loss. By the time of JDK 1.4 it was almost a non-issue. These days (and you can
test this yourself) making something synchronized has so little effect on performance that you can effectively discount it.
What can cause a performance hit is contention for resources. This issue is the same whether the resource in question is a synchronized block, accessing a single socket, using a single file descriptor, or placing all your SQL code inside transactions. If all clients are going to get blocked around a single resource then the application as a whole will suffer.
Therefore whenever you make a distributed application
you should consider how you can reduce contention for single objects. Ebay actually make a case for removing all transactions from their calls to the database. (!) In our case, it makes sense to reduce the synchronized code to the smallest logical blocks possible. You rarely need an entire method synchronized. The usual use-case I see is when somebody synchronizes the lock method. But even there it can make sense to synchronize on a different mutex rather than the Data class.
One of the questions you should be asking yourself around about now is: exactly what do you have that could potentially be changing that you would need to make atomic? There should really only be one or two objects that are shared between clients that are variable. The object holding the locks is one. The file descriptor is potentially another. Any others?