线程同步

线程同步的方法

1.同步代码块

synchronize(){

}

包住需要同步的代码段(保证仅包含对共享变量的操作)

括号中填同步监视器,也就是锁,可以是任何一个类的对象

关键就是多个线程要用同一把锁,否则达不到效果

实现Runnable接口方法

package Test1;

/**
 * @author rook1e
 * @creat 2022/1/9
 */

class Window implements Runnable{
    private int ticket = 100;
    Object obj = new Object();
    public void run(){
        while(true){
            synchronized(obj) {
                if (ticket > 0) {
                    System.out.println(Thread.currentThread().getName() + ":" + ticket);
                    --ticket;
                } else {
                    break;
                }
            }
        }
    }
}


public class WindowTicket {
    public static void main(String[] args) {
        Window window = new Window();

        Thread t1 = new Thread(window);
        Thread t2 = new Thread(window);
        Thread t3 = new Thread(window);

        t1.setName("Window 1");
        t2.setName("Window 2");
        t3.setName("Window 3");

        t1.start();
        t3.start();
        t2.start();
    }
}

继承Thread类方法

package Test1;

/**
 * @author rook1e
 * @creat 2022/1/9
 */

class Window extends Thread{
    private static int ticket = 100;
    private static Object obj = new Object();
    public void run(){
        while(true){
            synchronized(obj) {
                if (ticket > 0) {
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName() + ":" + ticket);
                    --ticket;
                } else {
                    break;
                }
            }
        }
    }
}


public class WindowTicket {
    public static void main(String[] args) {
        Window window1 = new Window();
        Window window2 = new Window();
        Window window3 = new Window();
        window1.setName("window1");
        window2.setName("window2");
        window3.setName("window3");
        window1.start();
        window2.start();
        window3.start();
    }
}

 

特别的,如果每次new一个对象有些麻烦,我们可以直接使用当前对象this,更简便一点

但是要注意如果使用继承方式实现多线程时,需要new多个类,要明确当前的this是否是唯一的,换句话说就是,多个线程需要共用同一个this!

 

2.同步方法 

对仅对共享变量操作的方法,直接声明为同步方法

package Test1;

/**
 * @author rook1e
 * @creat 2022/1/10
 */


class Window1 implements Runnable{
    private int ticket = 100;

    public void run(){
        while(true){
            show();
        }
    }

    private synchronized void show(){
        if(ticket > 0){
            System.out.println(Thread.currentThread().getName() + ":" + ticket);
            -- ticket;
        }
    }
}
public class WindowSynchronized {
    public static void main(String[] args) {
        Window1 window1 = new Window1();
        Thread t1 = new Thread(window1);
        Thread t2 = new Thread(window1);
        Thread t3 = new Thread(window1);

        t1.setName("Window1");
        t2.setName("Window2");
        t3.setName("Window3");

        t1.start();
        t2.start();
        t3.start();
    }
}

不能将run方法声明为同步方法,否则是错误的,要保证同步方法中仅包含对共享变量的操作。

 

3.lock锁

使用java中定义的锁,包含用lock方法和unlock方法包含需要同步的代码段,实现解决线程安全问题

下面是实现Runnable接口方法实现多线程

package Test1;

import java.util.concurrent.locks.ReentrantLock;

/**
 * @author rook1e
 * @creat 2022/1/8
 */

class MthreadTickets implements Runnable{
    public static int tickets = 100;
    private ReentrantLock lock = new ReentrantLock();

    @Override
    public void run() {
        while(true){
            lock.lock();//上锁
            if(tickets > 0){
                System.out.println(Thread.currentThread().getName() + ":" + "id " + tickets);
                tickets -- ;
            }else{
                break;
            }
            lock.unlock();//解锁

            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

public class ThreadTickets {
    public static void main(String[] args) {
        MthreadTickets mthreadTickets = new MthreadTickets();
        Thread t1 = new Thread(mthreadTickets);
        Thread t2 = new Thread(mthreadTickets);
        Thread t3 = new Thread(mthreadTickets);

        t1.setName("窗口1");
        t2.setName("窗口2");
        t3.setName("窗口3");

        t1.start();
        t2.start();
        t3.start();
    }
}

继承Threa类方式实现多线程,同一样的,多个线程需要共用同一把锁,因此声明锁时需要加上static关键字来实现唯一性

package Test1;

import java.util.concurrent.locks.ReentrantLock;

/**
 * @author rook1e
 * @creat 2022/1/9
 */

class Window extends Thread{
    private static int ticket = 100;
    private static ReentrantLock lock = new ReentrantLock();//注意加static关键字的原因
    public void run(){
        while(true){
            lock.lock();
            if (ticket > 0) {
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() + ":" + ticket);
                --ticket;
            } else {
                break;
            }
            lock.unlock();
        }
    }
}


public class WindowTicket {
    public static void main(String[] args) {
        Window window1 = new Window();
        Window window2 = new Window();
        Window window3 = new Window();
        window1.setName("window1");
        window2.setName("window2");
        window3.setName("window3");
        window1.start();
        window2.start();
        window3.start();
    }
}

 

package Test1;

import java.util.concurrent.locks.ReentrantLock;

/**
* @author rook1e
* @creat 2022/1/9
*/

class Window extends Thread{
private static int ticket = 100;
private static ReentrantLock lock = new ReentrantLock();
public void run(){
while(true){
lock.lock();
if (ticket > 0) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + ":" + ticket);
--ticket;
} else {
break;
}
lock.unlock();
}
}
}


public class WindowTicket {
public static void main(String[] args) {
Window window1 = new Window();
Window window2 = new Window();
Window window3 = new Window();
window1.setName("window1");
window2.setName("window2");
window3.setName("window3");
window1.start();
window2.start();
window3.start();
}
}
posted @ 2022-01-10 14:31  Rook1e  阅读(36)  评论(0编辑  收藏  举报