Backend Table/Row Locking Structure using CTE Queries
No, the locks will not change because of CTEs. What you have shown are non-recursive CTEs. These are just another way of introducing a sub-query into the SQL statement. The query
with some_CTE as
(
  select &lt; whatever &gt; from &lt; something &gt;
)
select * from some_CTE;

is semantically identical to
select * from
(
  select &lt; whatever &gt; from &lt; something &gt;
) as some_alias;

As the query optimizer is free to rearrange your statement into any logical equivalent it is likely these two statements will end up with identical execution plans.  (For very complex queries, where the CTE or the main query has many joins, or the CTE is referenced many times, the execution plans may be different, but this is an artefact of the optimization, not a fundamental property of how CTEs work.)
This paragraph is tangential to your main point about locking, but worth knowing. You say &quot;When the SELECT for CTE1 is finished..&quot; It doesn't necessarily work like that. The execution may proceed in any manner that satisfies the meaning of our query but does not have to follow the sequence in which it was written. See here and here for examples of how execution order may differ to written order.
As to your main question &quot;I was under the impression that .. when the SELECT .. completes the tables are released. Is that incorrect?&quot; I'll refer you to this Microsoft page:

The behavior of READ COMMITTED depends on the setting of the READ_COMMITTED_SNAPSHOT database option:
If READ_COMMITTED_SNAPSHOT is set to OFF (the default), the Database Engine uses shared locks to prevent other transactions from modifying rows while the current transaction is running a read operation. The shared locks also block the statement from reading rows modified by other transactions until the other transaction is completed. The shared lock type determines when it will be released. Row locks are released before the next row is processed. Page locks are released when the next page is read, and table locks are released when the statement finishes.

Here is another explanation which may explain it better. Both sources make clear that the granularity of locking (row, page or table) affect when the lock is released. There are many things that affect this, including system configuration and lock escalation.
I'll note also that your example uses UNION. This removes duplicates from the results. You may get different lock behaviour using UNION ALL, but that leaves duplicates and could return more rows, depending on your data.