java - 线程与单例对象或字符串的同步连接

标签 java multithreading thread-safety

System.out.println("嘿,明白了......");从未在我的程序中执行过

由于synchronized关键字,我可以理解它,但实际上发生了什么。

从 CFG 类调用 TestJoin 类,问题出在该类

 class TestJoin implements Runnable{

    public String x;

    TestJoin(String x){
        this.x= x;

    }

    public void testJoin() {
        System.out.println("b4"+x);
        synchronized(x) {
            System.out.println(x);
            ThreadJoining t1 = new ThreadJoining("2");

            // thread t1 starts
            t1.start();
            System.out.println("you fool");
            try{
                System.out.println(
                    "Current Thread: "+ 
                    Thread.currentThread().getName()
                );
                t1.join();
               //never this line is executed
               System.out.println("hey got it....");
            }catch(Exception ex){
                System.out.println(
                       "Exception has " +
                       "been caught" + ex
                );
            }
        }
    }

    @Override
    public void run() {
            testJoin();
    }
}

只需创建另一个从 TestJoin 类调用的线程

class ThreadJoining extends Thread{
        String c;
        ThreadJoining(String co){
            c=co;
        }
        @Override
        public void run()
        {
            synchronized(c) {
                for (int i = 0; i < 2; i++){
                try{
                    Thread.sleep(500);
                    System.out.println(
                             "Current Thread: " +
                             Thread.currentThread().getName()
                    );
                }catch(Exception ex){
                    System.out.println(
                                "Exception has" +
                                " been caught" + ex
                    );
                }
                System.out.println(i);
            }
        }
    }
}

主类执行从这里开始

public class GFG{
    public static void main (String[] args){

        Runtime.getRuntime().addShutdownHook(new Thread() {
            public void run() {
                System.out.println("Bye Bye");
            }
        });
        new Thread(new TestJoin("1")).start();
        new Thread(new TestJoin("1")).start();
        new Thread(new TestJoin("2")).start();
        new Thread(new TestJoin("3")).start();

     }
}

上述执行的输出

b41
1
b43
3
b42
2
b41
you fool
Current Thread: Thread-4
you fool
Current Thread: Thread-1
you fool
Current Thread: Thread-3

第二次编辑:

仅当我与字符串或单例对象同步时才会出现上述问题, 如果我使用一个新对象它的完美文件

示例,使用普通对象同步

public class GFG{
        public static void main (String[] args){

            Runtime.getRuntime().addShutdownHook(new Thread() {
                public void run() {
                    System.out.println("Bye Bye");
                }
            });
           Sample s =  new Sample();
           new Thread(new TestJoin(s)).start();
           new Thread(new TestJoin(s)).start();
           new Thread(new TestJoin(new Sample())).start();
           new Thread(new TestJoin(new Sample())).start();

        }
    }

public class TestJoin implements Runnable{

    public Sample x;
    TestJoin(Sample x){
        this.x= x;

    }

    public void testJoin() {
        System.out.println("b4"+x);
        synchronized(x) {
            System.out.println(x);
    ThreadJoining t1 = new ThreadJoining("2");

    // thread t1 starts
    t1.start();
    System.out.println("you fool");
    try
    {
        System.out.println("Current Thread: "
              + Thread.currentThread().getName());
        t1.join();
        System.out.println("hey got it....");
    }

    catch(Exception ex)
    {
        System.out.println("Exception has " +
                            "been caught" + ex);
    }
        }
    }

    @Override
    public void run() {
            testJoin();
    }
}

class ThreadJoining extends Thread{
    String c;
    ThreadJoining(String co){
        c=co;
    }

    @Override
    public void run(){
        synchronized(c) {
            for (int i = 0; i < 2; i++){
                try{
                    Thread.sleep(500);
                    System.out.println(
                        "Current Thread: " +
                        Thread.currentThread().getName()
                    );
                }catch(Exception ex){
                    System.out.println(
                        "Exception has" +
                        " been caught" + ex
                    );
                }
                System.out.println(i);
            }
        }
    }
}

public class Sample {

}

输出

b4Sample@a5c4778
b4Sample@27efa2ad
b4Sample@a5c4778
b4Sample@27507837
Sample@27507837
Sample@27efa2ad
Sample@a5c4778
you fool
you fool
Current Thread: Thread-4
you fool
Current Thread: Thread-3
Current Thread: Thread-1
Current Thread: Thread-6
0
Current Thread: Thread-6
1
hey got it....
Current Thread: Thread-5
0
Current Thread: Thread-5
1
hey got it....
Current Thread: Thread-7
0
Current Thread: Thread-7
1
hey got it....
Sample@a5c4778
you fool
Current Thread: Thread-2
Current Thread: Thread-8
0
Current Thread: Thread-8
1
hey got it....
Bye Bye

最佳答案

这是因为字符串常量是实习的,所以当您在 ThreadJoiningTestJoin 中同步 "2" 时,您实际上是在锁定同一个对象。

new TestJoin("2") 锁定 "2" 然后等待 new ThreadJoining("2")< 时,这会导致死锁 完成(这永远不会发生,因为它无法获得 "2" 上的锁定)。

关于java - 线程与单例对象或字符串的同步连接,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51852811/

相关文章:

java - 错误 : No suitable driver found for database on AWS RDS

java - JAXB 纯粹从接口(interface)编码

java - Vaadin 中组合框的 validator

java - 使用jsoup解析https(java)

Java 并发问题 - Locks 和 Synchronize 方法

c# - 如何使使用队列线程的异步方法安全

c# - 多线程无法正常执行

javascript - Nashorn 多线程编程

c# - 秒表耗时线程安全

c# - XElement 的添加操作是线程安全的吗?