Java 线程同步

本文探讨了线程同步的概念及其实现方式,并通过具体示例介绍了如何利用synchronized关键字实现线程同步,同时展示了ThreadLocal机制在解决线程间共享变量问题上的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

      


       看了一下线程的知识,写了一段线程同步的代码,结果却没按照想的结果来,就想肯定是没有理解,网上 看了一下别人写的,改了一下代码,结果也算是按照想的来了。现在总结一下线程同步。

       线程也是处理具有某个功能的一段代码,只是它的运行机制有点不同,它是在进程中的,一个进程有一个主线程,可通过主线程创建很多的子线程,线程启动之后,会按照它们的方式进行运行,不受程序员控制,不知道线程如何运行完,运行的结果也不相同。

      在线程这一块需要知道线程所使用的资源:CPU和内存资源。线程根据CPU的时间片轮转来切换;线程可以访问所在对象的内存资源。

     

      1.单对象多线程:共享变量和执行步骤

      2.多对象多线程


写个小例子,好体会:

public class ThreadTestExample {
    public static void main(String []args)
    {
        ThreadA examA = new ThreadA();
        Thread threadExamA = new Thread(<span style="color:#ff6666;">examA</span>,"ThreadA");
        
    //  ThreadA examB = new ThreadA();
        Thread threadExamB = new Thread(<span style="color:#ff6666;">examA</span>,"ThreadB");      <span style="color:#ff6666;">//threadExamA和threadExamB使用同一个对象examA,所以他们访问同一内存区</span>
        
        threadExamA.start();
        threadExamB.start();
        
    }
}
class ThreadA implements Runnable
{

	String name;
	double money = 100000;     //money在这里定义的是全局变量,所以<span style="color:#ff6666;">threadExamA和threadExamB都可以访问到它,所以应该确保有顺序的访问</span>

	
	@Override
	public void run() {
		// TODO Auto-generated method stub
		
	synchronized(this)     //使用synchronized关键字同步这两个线程,一个访问完成后一个才能访问,this指代的是examA这个对象
	{
		
    	if(Thread.currentThread().getName().equals("ThreadA"))
    	{
    		for(int i=0;i < 5; i++)
    		{
    			money -= 20000;
    			try{
    				Thread.sleep(1000);
    			}catch(InterruptedException e)
    			{}
    			
    			System.out.printf("\n%s","I am ThreadA,"+"I have money:"+money+";");
    		}
    	}
    	if(Thread.currentThread().getName().equals("ThreadB"))
    	{
    		
    		for(int i=0;i < 5; i++)
    		{
    			money += 20000;
    			try{
    				Thread.sleep(1000);
    			}catch(InterruptedException e)
    			{}
    			System.out.printf("\n%s","I am ThreadB,"+"I have money:"+money+";");
    		}
    	}
    }
	}
    	
  }
	

里面的注释只是解释了单对象多线程运行时,要注意内存中的全局变量,如果将money这个变量写到run方法中,则它表示局部变量,那么这两个线程则访问的不是同一个变量,输出的结果肯定是不一样的。

    单对象多线程要注意的是线程访问的变量是全局变量还是局部变量,如果是全局变量,一定要注意线程的同步,用synchronized来标识同步,这个关键字可以按照上面那样写,也可以写在方法前面,这个方法在run中调用。如果是局部变量,那么它们访问的则不是同一个,运行结果也就没有影响。

    使用多对象多线程,那么表示的意思是每个线程的访问空间都不一样,那么他们处理的结果之间不会相互影响。要注意不管是全局变量还是局部变量,都只在一个线程中起作用。


  使用ThreadLocal机制

ThreadLocal是JDK引入的一种机制,它用于解决线程间共享变量,使用ThreadLocal声明的变量,即使在线程中数据全局变量,针对每个线程来讲,这个变量也是独立的。

下面是一个例子:

解决共享变量问题方案三
class MyRunner3 implements Runnable
{
    public ThreadLocal<Integer> tl = new ThreadLocal<Integer>();
    
    public void run() 
    {
        System.out.println(Thread.currentThread().getName() + " Start.");
        for (int i = 0; i <= 100; i++)
        {
            if (tl.get() == null)
            {
                tl.set(new Integer(0));
            }
            int sum = ((Integer)tl.get()).intValue();
            sum+= i;
            tl.set(new Integer(sum));
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        
        System.out.println(Thread.currentThread().getName() + " --- The value of sum is " + ((Integer)tl.get()).intValue());
        System.out.println(Thread.currentThread().getName() + " End.");
    }
}


private static void sharedVaribleTest4() throws InterruptedException
{
    MyRunner3 runner = new MyRunner3();
    Thread thread1 = new Thread(runner);
    Thread thread2 = new Thread(runner);
    thread1.setDaemon(true);
    thread2.setDaemon(true);
    thread1.start();
    thread2.start();
    thread1.join();
    thread2.join();
}

未完待续...
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值