A process is a collection of threads (usually only one), so your second question is always true.
Yes. Most processes have just one thread, but sophisticated ones like deployed Flask apps can have multiple threads.
In a deployed Flask app, the Flask infrastructure creates a new thread for each incoming web request. That thread then calls our code. Our code looks exactly the same as it always does, but now we have to make sure it is thread safe, because several threads might be executing our code at once.
It may help to anthropomorphize this. Imagine a recipe (our code), being executed by multiple chefs at once. There are shared resources; maybe the oven. Can all the chefs work together?
As I just said, each request is a different thread. To play well with each other, they may need to lock resources. They also need to think about sharing the database (tables). That's where transactions come in.
No, this has nothing to do with the requests reading (which was single-threaded and didn't connect to the database). This is only an issue for our back-end code.
A condition object is a lock that will wake up the thread that is waiting for the lock. When a thread asks for the resource and the resource is in use, the condition puts the thread to sleep and wakes it up when the resource becomes available.