JAVA--线程同步

  继昨天线程介绍后,今天我又把线程中的同步问题总结了一下,现在就和大家一起探讨一下。

  线程加锁有什么用处呢?举个例子:比如你现在有30000块大洋在银行存着,现在你到银行取钱,当你输入密码完成后,已经输入取款金额,比如你输入的是20000,就是在银行给你拿钱这个时刻,你老婆也去银行取这笔钱,你老婆同样取20000,因为此时你的账上仍然是30000,所以银行同样的操作在你老婆那端有进行了一遍,这样当你们两个完成各自操作后,银行记录的你账上还应该有10000块存款,这样是不是很爽。解决这个问题就用到了线程加锁的知识,下面就让我们一起来学习一下吧。

一、未处理线程同步的一个例子:

public class TextSync implements Runnable{

    /**未处理线程同步
     * @param args
     */
    Time time = new Time();
    public static void main(String[] args) {
        TextSync text = new TextSync();
        Thread t1 = new Thread(text);
        Thread t2 = new Thread(text);
        t1.setName("t1");
        t2.setName("t2");
        t1.start();
        t2.start();
    }

    @Override
    public void run() {
        time.add(Thread.currentThread().getName());
    }
}
class Time {
    private static int num = 0;
    public void add(String name){
        try {
            num++;
            //当第一个线程执行到此时,num变成了1,第一个线程暂停一秒,
            //第二个线程开始执行,当第二个线程执行到此时,num变成了2,第二个线程暂停一秒,
            //第一个线程此时的num同样变成了2,所以最终的结果均为2;
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(name+"是第"+num+"个执行的线程。");
    }
}

输出结果:

二、线程同步

public class TextSynctwo implements Runnable{

    /**线程同步
     * @param args
     */
    Time1 time = new Time1();
    public static void main(String[] args) {
        TextSynctwo text = new TextSynctwo();
        Thread t1 = new Thread(text);
        Thread t2 = new Thread(text);
        t1.setName("t1");
        t2.setName("t2");
        t1.start();
        t2.start();
    }

    @Override
    public void run() {
        time.add(Thread.currentThread().getName());
    }
}
class Time1 {
    private static int num = 0;
    
    //synchronized锁定当前线程,可以在方法定义时进行声明,或采用在方法中进行设置。
    public synchronized void add(String name){
        //synchronized (this) {//锁定当前线程,防止此时被别的线程执行
            try {
                num++;
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(name+"是第"+num+"个执行的线程。");
        //}
    }
}

输出结果:

三、死锁

public class TestDeadLock implements Runnable{

    /**死锁
     * @param args
     */
    private int flag = 0 ; 
    static Object o1 = new Object();
    static Object o2 = new Object();
    public static void main(String[] args) {
        TestDeadLock td1 = new TestDeadLock(); 
        TestDeadLock td2 = new TestDeadLock(); 
        td1.flag = 1;
        td2.flag = 2;
        Thread t1 = new Thread(td1); 
        Thread t2 = new Thread(td2);
        t1.setName("t1");
        t2.setName("t2");
        t1.start();
        t2.start();
    }

    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName());
        if(flag == 1){
            synchronized(o1){
                try {
                    Thread.sleep(5000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                synchronized(o2){
                    System.out.println("1");
                }
            }
        }
        if(flag == 2){
            synchronized(o2){
                try {
                    Thread.sleep(5000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                synchronized(o1){
                    System.out.println("2");
                }
            }
        }
    }
}

四、锁定

public class TT implements Runnable{

    /**锁定
     * @param args
     */
    int b = 100;
    public static void main(String[] args) {
        TT tt = new TT();
        Thread th = new Thread(tt);
        th.start();
        try {
            tt.m2();
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println(tt.b);
    }

    @Override
    public void run() {
        try {
            m1();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
    private synchronized void m1() throws Exception{
        b = 1000;
        Thread.sleep(5000);
        System.out.println("b="+b);
    }
    private synchronized void m2() throws Exception{
        Thread.sleep(2500);
        b = 2500;
    } 
}

对于锁定这个我有一个疑问,还望大神们给予指点,现在的输出结果:

我想问的就是,问什么m2先执行,m1要等m2执行完毕后方可执行。

希望大家给予答复,谢谢

转载于:https://www.cnblogs.com/AndroidJotting/p/3937019.html

### 回答1: 您好!如果我理解正确的话,您的问题是关于JMU Java 07多线程同步访问的。以下是我的回答: 多线程编程是指在一个程序中同时执行多个线程的编程技术。多线程编程在提高程序性能、增强程序交互性等方面有很大的优势,但也会引入一些问题,比如线程安全问题。 当多个线程同时访问共享资源时,可能会出现线程不安全的问题,比如数据竞争、死锁等。为了避免这些问题,我们需要使用同步机制来确保线程安全。 Java中提供了多种同步机制,比如synchronized关键字、ReentrantLock类、Semaphore类等。这些同步机制都可以用来保证多线程访问共享资源的安全性。 其中,synchronized是最常用的同步机制之一。在Java中,synchronized关键字可以用来修饰方法或代码块,以实现同步访问共享资源。synchronized可以保证在同一时间只有一个线程可以访问共享资源,从而避免了数据竞争等线程安全问题。 除了synchronized之外,Java还提供了一些其他的同步机制,比如ReentrantLock类和Semaphore类。ReentrantLock类提供了比synchronized更灵活的锁机制,可以实现可重入锁、公平锁等功能。Semaphore类可以控制同时访问共享资源的线程数量,从而避免资源被过度占用的问题。 总的来说,多线程编程是一项复杂而重要的技术,需要仔细研究和实践。在实际开发中,我们需要根据具体的需求选择合适的同步机制来确保多线程访问共享资源的安全性。 ### 回答2: 多线程编程是在当前计算机领域中最为常见的技术之一,它可以利用计算机中的多核处理器来使程序运行更加高效。但是,多线程编程中可能会出现的最大问题就是线程安全,因为线程之间可能会访问相同的资源,从而导致竞态条件。 在Java中,可以通过使用synchronized关键字来实现同步访问,从而避免线程安全问题。synchronized关键字可以用于两种不同的情形:同步方法和同步块。在同步方法中,方法是同步的,即每个线程在执行该方法时都需要获取该对象的锁,如果该锁已经被其他线程获取,则需要等待直到此锁被释放。在同步块中,需要手动指定锁,即每个线程在执行同步块时需要获取该指定锁,其他线程如果需要访问该代码块中的共享资源也需要获取该指定锁,这样就保证了该代码块中的所有共享资源的同步访问。 除了synchronized关键字外,Java还提供了其他一些同步机制来实现线程安全,如ReentrantLock类和CountDownLatch类等。ReentrantLock类可以实现更为灵活的同步访问控制,但需要手动释放锁;而CountDownLatch类则用于同步一个多个线程,使这些线程在某个条件满足之前一直处于等待状态。 在进行多线程编程时,应该尽量避免对同步访问造成瓶颈,应该通过减小同步代码块的范围等方式来提高程序的效率。此外,多线程编程时还应该进行线程安全性的测试,以确保程序能够正确地运行。 ### 回答3: 在Java中,多线程是一种非常常见的编程方式。由于多线程的特点,对共享资源的访问会出现竞争的情况,这种竞争可能会导致数据不一致或程序异常等问题。因此,在多线程编程中,我们需要采取一些措施来保证共享资源的访问能够正确、有序地进行,这就是同步机制。 同步机制包括两种方式:锁和信号量。锁是最基本的同步机制。锁有两种类型:互斥锁(Mutex)和读写锁(ReadWriteLock)。互斥锁用于保护共享资源,保证同一时间只有一个线程可以访问它,其他线程需要等待锁释放后才能继续访问。读写锁用于读写分离场景,提高了多线程访问共享资源的并发性。读写锁支持多个线程同时读取共享资源,但只允许一个线程写入共享资源。 信号量是一种更加高级的同步机制。信号量可以用来控制并发线程数和限制访问共享资源的最大数量。在Java中,Semaphore类提供了信号量的实现。Semaphore可以控制的线程数量可以是任意的,线程可以一起执行,也可以分批执行。 除了锁和信号量,Java还提供了一些其他同步机制,比如阻塞队列、Condition等。阻塞队列是一种特殊的队列,它支持线程在插入或者删除元素时阻塞等待。Condition是一种锁的增强,它可以让线程在某个特定条件下等待或者唤醒。 在多线程编程中,使用同步机制需要注意以下几点。首先,同步机制要尽可能的保证资源访问的公平性,避免因为某些线程执行时间过长导致其他线程等待时间过长。其次,同步机制要尽可能的避免死锁的发生,尤其要注意线程之间的依赖关系。最后,同步机制的实现要尽可能地简单,避免过于复杂的代码实现带来的维护成本。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值