...everything is in a transaction therefore the locks (in accord with Oracle's usual configuration) are only held from an update to a commit. (As opposed to from a select to a commit, which you'd find in most other databases...
The reason for this is that there are two common types of locking strategies (isolation levels): Repeatable Read and Cursor Stability. Repeatable Read means just that. Once you've read a record, you can go back an reread it and be guarenteed that you will get the identical data again. This tends to accumulate locks which can lead to lock escalation (row to page to table to tablespace/dbspace), but if you need to be sure that when the commit is issued that all the data the app depends on is consistent, this is what you need (financial apps particularly). Cursor Stability only maintains share locks on "the current row" (and maybe the one on either side in the access order) and exclusive locks when when a row has been inserted or updated. I don't know about Oracle, but a 'select...for update' in DB2 obtained a share lock and was only escalated to exclusive once the update command was issued. (Share locks allow multiple readers and no writers, exclusive locks allow no other readers or writers.)
There are two other locking strategies: Read Committed and Read Uncommited. These are dangerous in the hands of those with a "little learning". Read Committed is like Cursor Stability without the share locks, meaning you aren't even guarenteed that the row you just read can be re-read again. In a high volume read-only application, this is great. Read Uncommited, sometimes called Dirty Read, means you can read any row regardless of what others are doing, meaning the row you get could have old values. This is great for data warehousing where you are only interested in aggregate values, not in particular values. In transactional systems, where the inexperienced want to use it for "performance", it is disaster.