In Java, a
Semaphore is implemented entirely in Java. This means there is no native resource to clean up once it is not longer needed. It can be cleaned up like normal Java objects.
Closeable is needed where there is a native resource which is associated with the on heap Java object. e.g. file Streams or Sockets. These external resources are more expensive and limited than objects on the heap and could run out long before a GC is triggered and has cleaned them up.
Note: a GC is not enough to clean up these resource, the background thread closing them also has to run to free those resources. In HotSpot/JVM there is a Finalizer thread which closes these resources and if a few are slow to close it can lead to resource starvation.