clFinish() will wait for all operations enqueued in the command queue to complete.
clWaitForEvents() will only wait for those events that you asked to wait for.
For every command you enqueue to Command Queue, the run-time will return back a "cl_event" - which can use used to identify the command to the runtime.
You can collect the interested events separately and then issue a clWait() on them.
OR You can specify the selected events in the "eventWaitList" of any subsequently issued command. Such a command, will wait for its dependents to complete before commencing execution.
So, these wait lists ( who waits on who) itself can itself be seen as a precendence graph.