线程的同步和锁问题

Be_nurturing 2016-07-10 11:35:47
我是一个初学java的菜鸟,想问下,怎样不用锁能够解决多个线程间操作共享数据的问题,比如有100张票,多个线程操作,用的是同步代码块,或是同步方法,这些都是获取了锁。
现在有一个需求是不用获取“”锁“”也可以解决多个线程操作共享数据的问题,也不会出现线程安全的问题。急,有会的大神帮帮吧
public class TicectDemo implements Runnable{

private int num = 100;

@Override
public void run() {
try {
saleTicket();
} catch (InterruptedException e) {
e.printStackTrace();
}
}

public void saleTicket() throws InterruptedException{

while(num >0){
synchronized(TicectDemo.class){
if(num >0){
System.out.println(Thread.currentThread().getName() + "...sale..." + num--);
}
Thread.sleep(10);
}
}
}

public static void main(String[] args) {

Runnable ticectDemo = new TicectDemo();

Thread thread1 = new Thread(ticectDemo);
Thread thread2 = new Thread(ticectDemo);
Thread thread3 = new Thread(ticectDemo);
Thread thread4 = new Thread(ticectDemo);

thread1.start();
thread2.start();
thread3.start();
thread4.start();
}
}
...全文
228 6 打赏 收藏 转发到动态 举报
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
define_us 2016-07-12
  • 打赏
  • 举报
回复
其实这代码并不难,但是术业有专攻,你可能不理解。 新建一个线程ThreadManager,然后让所有线程运行,但是工作线程都会在条件变量处循环等待。这时,ThreadManager挨个通过改变对应的环境变量来激活指定线程。每激活一个队列中最开始的线程,就把这个线程放在队列的最后边,然后循环等待该线程改变自己的条件变量。发现自己的条件变量被改变后,就去激活下一个线程。为了获得改变工作线程条件变量的能力,还需要定义一个借口。就是所谓的第二个类。 其实你可以理解为ThreadManager去调用了工作线程,然后等待工作线程返回,类似于函数调用。所以说牺牲了同步性。在上述线程执行的工作里,实际上只有Thread.sleep(10);这一句话是并发执行的。 另外,你们老板或许能透露点为啥这样干的理由,我也能长长见识。
Be_nurturing 2016-07-12
  • 打赏
  • 举报
回复
引用 4 楼 define_us 的回复:

package s1;
import java.util.LinkedList;  

public class TicectDemo extends Thread implements Concur{
	
	private static int num = 100;
	private static ThreadManager manager;
	private volatile boolean concur = false;
	
	private String threadName;
	
	public boolean getConcur(){
		return concur;
	}
	public void setConcur(){
		concur = true;
	}
	public String MyGetName(){
		return threadName;
	}
	
	@Override
	public void run() {
		threadName = Thread.currentThread().getName();
		try {
			saleTicket();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}

	}
	
	public  void  saleTicket() throws InterruptedException{
	
		while(num >0){
			while(true){
				if(concur == true){
					break;
				}
			}

			if(num >0){
				System.out.println(Thread.currentThread().getName() + "...sale..." + num--);
			}
			if(num == 0)
				System.exit(0);
			concur = false;
			manager.flag = true;
			
			
			Thread.sleep(10);

		}
	}
	
	public static void main(String[] args) {
	
		Runnable ticectDemo = new TicectDemo();
		manager = new ThreadManager();
	
		TicectDemo thread1 = new TicectDemo();
		TicectDemo thread2 = new TicectDemo();
		TicectDemo thread3 = new TicectDemo();
		TicectDemo thread4 = new TicectDemo();
		
		manager.list.add(thread1);
		manager.list.add(thread2);
		manager.list.add(thread3);
		manager.list.add(thread4);
		
		thread1.start();	
		thread2.start();
		thread3.start();
		thread4.start();
		manager.start();
		

	}
} 


class ThreadManager extends Thread{
	public LinkedList<Concur> list = new LinkedList<Concur> ();
	public volatile boolean flag = true;
	
	

	public void MyNotify(){
		list.removeFirst();  
	}
	public void run(){
		while(true){
			if (flag == true){
				flag =false;
				//将链表的第一个放到最后一个
				Concur a = list.getFirst();
				list.removeFirst();
				list.addLast(a);
				System.out.println("this is "+a.MyGetName());
				a.setConcur();
			}

				
		}
	}

}

interface Concur {
	public boolean getConcur();
	public void setConcur();
	public String MyGetName();
	
}

实际上线程同步有楼上所说的JUC方法,也有你写的这种,还有object的notify,wait方法。但是如果你实在既不想用synchronized也不想用lock。还有这种上面这种非常滑稽性能极低的方法,最大程度的牺牲了同步性。这种方法存在的唯一价值就是激怒你的老板。
这位朋友先感谢你这么晚还帮别人解决问题,我想说的是,水平比较差,对于你后两个加的类不是很理解,可以大概的讲一下思路或是原理吗,因为这个事我的领导给我出的问题,不用锁也要解决同步的问题,你写的已经很清楚了,但是我理解的还不是很透彻,希望在帮助解释下,我可以反复琢磨下。
define_us 2016-07-11
  • 打赏
  • 举报
回复

package s1;
import java.util.LinkedList;  

public class TicectDemo extends Thread implements Concur{
	
	private static int num = 100;
	private static ThreadManager manager;
	private volatile boolean concur = false;
	
	private String threadName;
	
	public boolean getConcur(){
		return concur;
	}
	public void setConcur(){
		concur = true;
	}
	public String MyGetName(){
		return threadName;
	}
	
	@Override
	public void run() {
		threadName = Thread.currentThread().getName();
		try {
			saleTicket();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}

	}
	
	public  void  saleTicket() throws InterruptedException{
	
		while(num >0){
			while(true){
				if(concur == true){
					break;
				}
			}

			if(num >0){
				System.out.println(Thread.currentThread().getName() + "...sale..." + num--);
			}
			if(num == 0)
				System.exit(0);
			concur = false;
			manager.flag = true;
			
			
			Thread.sleep(10);

		}
	}
	
	public static void main(String[] args) {
	
		Runnable ticectDemo = new TicectDemo();
		manager = new ThreadManager();
	
		TicectDemo thread1 = new TicectDemo();
		TicectDemo thread2 = new TicectDemo();
		TicectDemo thread3 = new TicectDemo();
		TicectDemo thread4 = new TicectDemo();
		
		manager.list.add(thread1);
		manager.list.add(thread2);
		manager.list.add(thread3);
		manager.list.add(thread4);
		
		thread1.start();	
		thread2.start();
		thread3.start();
		thread4.start();
		manager.start();
		

	}
} 


class ThreadManager extends Thread{
	public LinkedList<Concur> list = new LinkedList<Concur> ();
	public volatile boolean flag = true;
	
	

	public void MyNotify(){
		list.removeFirst();  
	}
	public void run(){
		while(true){
			if (flag == true){
				flag =false;
				//将链表的第一个放到最后一个
				Concur a = list.getFirst();
				list.removeFirst();
				list.addLast(a);
				System.out.println("this is "+a.MyGetName());
				a.setConcur();
			}

				
		}
	}

}

interface Concur {
	public boolean getConcur();
	public void setConcur();
	public String MyGetName();
	
}

实际上线程同步有楼上所说的JUC方法,也有你写的这种,还有object的notify,wait方法。但是如果你实在既不想用synchronized也不想用lock。还有这种上面这种非常滑稽性能极低的方法,最大程度的牺牲了同步性。这种方法存在的唯一价值就是激怒你的老板。
小小鸟飞飞 2016-07-10
  • 打赏
  • 举报
回复
使用ReenTrantLock类呢 里面的lock()方法加锁,unlock()释放锁
Be_nurturing 2016-07-10
  • 打赏
  • 举报
回复
现在只是知道使用同步的方法,主要是不用锁就可以,但是还没想明白
帅帅的波 2016-07-10
  • 打赏
  • 举报
回复
num 使用volatile 关键字呢

62,625

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧