import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; public class MyThread implements Runnable { private Lock lock = new ReentrantLock(); public void run() { lock.lock(); try { // Critical section System.out.println(Thread.currentThread().getName() + ": Hello, World!"); } finally { lock.unlock(); } } public static void main(String[] args) { MyThread myThread = new MyThread(); Thread t1 = new Thread(myThread, "Thread 1"); Thread t2 = new Thread(myThread, "Thread 2"); t1.start(); t2.start(); } }Explanation: In this example, a MyThread class implements the Runnable interface and overrides the run() method. Inside the run() method, the lock() method is called to acquire the lock, and the unlock() method is called in a finally block to release the lock. The critical section of the code is the line that prints "Hello, World!" to the console. The class also instantiates a ReentrantLock object and assigns it to a Lock variable called lock. The ReentrantLock class is part of the java.util.concurrent.locks package library, which provides advanced locking mechanisms. The main() method creates two threads and starts them. Since both threads share the same instance of MyThread, they both try to acquire the same lock, ensuring that only one thread can access the critical section at a time. In summary, the Lock interface is a powerful tool for implementing thread-safe code that prevents race conditions and data corruption. The java.util.concurrent.locks package library provides advanced locking mechanisms to help developers write efficient and scalable multithreaded applications.