# Python Threading Module

The `threading` module constructs higher-level threading interfaces on top of the lower level `_thread` module. It allows you to run multiple threads (tasks, function calls) at the same time.

## Importing the Module

```python
import threading
```

## Creating and Starting Threads

To create a thread, you create an instance of the `Thread` class and pass it the function you want to run via the `target` argument.

```python
import threading
import time

def print_numbers():
    for i in range(5):
        time.sleep(1)
        print(f"Number: {i}")

def print_letters():
    for letter in 'abcde':
        time.sleep(1)
        print(f"Letter: {letter}")

# Create threads
t1 = threading.Thread(target=print_numbers)
t2 = threading.Thread(target=print_letters)

# Start threads
t1.start()
t2.start()

# Wait for threads to complete
t1.join()
t2.join()

print("Done!")
```

## Thread Synchronization (Locks)

When multiple threads access shared resources, race conditions can occur. The `Lock` class solves this.

```python
import threading

x = 0
lock = threading.Lock()

def increment():
    global x
    for _ in range(100000):
        with lock:
            x += 1

t1 = threading.Thread(target=increment)
t2 = threading.Thread(target=increment)

t1.start()
t2.start()

t1.join()
t2.join()

print(f"Final value of x: {x}")
```

## Daemon Threads

A daemon thread runs in the background and does not prevent the program from exiting.

```python
# t = threading.Thread(target=background_task, daemon=True)
# t.start()
```

[[programming/python/python]]