1、多个线程用到同一个资源的话,必须lock
2、为了解决,在竞争的情况下,优先分配资源给A。就是A和B线程都同时在同一时刻需要资源x,然后的话也不清楚系统是具体怎样调度的。或者说怎样调度,都有可能出现上面的问题。解决方法是:在分配资源的时候再增加一个请求,用来排队。以前的请求是,如果这个时候申请然后这个时候也没人在用,就给它。现在的是如果B需要x,先要查看A是否需要。感觉有点像增加代码,然后使得线程判断次数增加,多次调度。所以感觉没有根本解决问题。
也不是说没解决,但是感觉解决了99.9%。hack,对于同一时刻到来的,还是随机化先进性读,或者先进性写了。T__T
怎么说呢,就是读者一来,先申请需要资源,而不是判定是否能拿资源,然后能拿就给它。我们需要的是先申请,然后就相当于锁定了资源x了,后来的写者再需要,需要检查申请队列中是否有读者,有就不行。
3、合法后立马addSignal,不然会出现多个写者同时操作的问题。
4、get, set方法是有用的,对于多线程,还可以维护资源不被多个线程修改,Lock
所以我的感觉是:如果是这样的:
写者先判定while (getNeedReader() > 0) { },判断失败的。
然后读者addReader(1);
然后写者while (getSignal() != 0) { } 也是失败的。
这样的话,结果还是给了写者。
很多人告诉我直接设置线程优先级,但是这样是不对的。因为线程的优先级只是说分配的时间片比较多,不保证上面的情况不能发生。
usingSystem;usingSystem.Collections.Generic;usingSystem.ComponentModel;usingSystem.Data;usingSystem.Diagnostics;usingSystem.Drawing;usingSystem.IO;usingSystem.Linq;usingSystem.Text;usingSystem.Threading;usingSystem.Threading.Tasks;usingSystem.Windows.Forms;namespaceWindowsFormsApp1 {public partial classForm1 : Form {static int signal = 0;//0:empty 1:read 2:write
static int numberReader = 0, numberWriter = 0;private static object obj = new object();private static object si = new object();private static object reader = new object();const int dis = 1000;staticStopwatch timer1;static int needReader = 0;classtemp {public string[] str;intgetSignal() {lock(si) {returnsignal;
}
}intgetNumber() {if (0 == getSignal()) return 0;else if (1 == getSignal()) returnnumberReader;else returnnumberWriter;
}void addSignal(intid) {lock(si) {if (id == 1) {
signal= 1;
numberReader++;
}else{
signal= 2;
numberWriter++;
}
}
}void cutSignal(intid) {lock(si) {if (id == 1) {
numberReader--;if (numberReader == 0) signal = 0;
}else{
numberWriter--;if (numberWriter == 0) signal = 0;
}
}
}voidaddStringRichText(String str) {lock(obj) {
Form1.richTextBox1.Text+=str;
Form1.richTextBox1.Text+= '\n';
Form1.richTextBox1.Focus();
Form1.richTextBox1.Select(Form1.richTextBox1.Text.Length,0);
Form1.richTextBox1.ScrollToCaret();
}
}void show(String[] str, intid) {
Console.Write(id+ "+++");for (int i = 0; i < str.Length; ++i) {
Console.Write(str[i]+ " ");
}
Console.WriteLine("\n");
}void addReader(intop) {lock(reader) {
needReader+=op;
}
}intgetNeedReader() {lock(reader) {returnneedReader;
}
}void semWait(intid) {if (id == 1) {
addReader(1); //首先需要申请需要资源,直接资源锁定
if (getSignal() != 2) {
addSignal(id);return;
}while (getSignal() == 2) { } //合法后立马addSignal
addSignal(1);
}else{while (getNeedReader() > 0) { }while (getSignal() != 0) { } //这句后面肯定要是addSignal,立马的
addSignal(2);
}
}void semSignal(intid) {if (id == 1) {
cutSignal(1);
addReader(-1);
}else{
cutSignal(2);
}
}public voidReader() {
addStringRichText("读者:" + str[0] + "线程创建");
Thread.Sleep(int.Parse(str[2]) * 1000);
addStringRichText("读者:" + str[0] + "在时间:" + (int)timer1.Elapsed.TotalSeconds + "请求读操作");/*进行读操作*/semWait(1);
addStringRichText("读者:" + str[0] + "在时间:" + (int)timer1.Elapsed.TotalSeconds + "开始读操作");
Thread.Sleep(int.Parse(str[3]) * 1000);
addStringRichText("读者:" + str[0] + "在时间:" + (int)timer1.Elapsed.TotalSeconds + "结束读操作");
semSignal(1);/*读操作进行完毕*/}private static object w = new object();public voidWriter() {
addStringRichText("写者:" + str[0] + "线程创建");
Thread.Sleep(int.Parse(str[2]) * 1000);
addStringRichText("写者:" + str[0] + "在时间:" + (int)timer1.Elapsed.TotalSeconds + "请求写操作");
semWait(2);/*进行读操作*/addStringRichText("写者:" + str[0] + "在时间:" + (int)timer1.Elapsed.TotalSeconds + "开始写操作");
Thread.Sleep(int.Parse(str[3]) * 1000);
addStringRichText("写者:" + str[0] + "在时间:" + (int)timer1.Elapsed.TotalSeconds + "结束写操作");
semSignal(2);/*读操作进行完毕*/}
}publicForm1() {
InitializeComponent();
}private void button1_Click(objectsender, EventArgs e) {
OpenFileDialog op= newOpenFileDialog();
op.ShowDialog();
op.Filter= "All files(*.*)|*.*";
StreamReader reader= null;try{string fileName =op.FileName;if (fileName == "") {return;
}
richTextBox1.Clear();
reader= newStreamReader(fileName, System.Text.Encoding.Default);string str =reader.ReadLine();
List list = new List();while (str != null) {string[] res = str.Split(' ');
temp zhu= newtemp();
zhu.str=res;if (str.Contains("R") || str.Contains("r")) {
Thread rThread= newThread(zhu.Reader);//rThread.Priority = ThreadPriority.AboveNormal;
rThread.Priority =ThreadPriority.AboveNormal;
list.Add(rThread);
}else if (str.Contains("W") || str.Contains("w")) {
Thread wThread= newThread(zhu.Writer);//wThread.Priority = ThreadPriority.BelowNormal;
list.Add(wThread);
}else{
MessageBox.Show("输入数据有错误!!!【每行数据后面不能有空格】,【文件结束不能有空行】");return;
}//MessageBox.Show(str);
str =reader.ReadLine();
}
timer1= new Stopwatch();//计时器类
timer1.Start();foreach (Thread i inlist) {
i.Start();
}
}catch(Exception error) {
MessageBox.Show("错误信息是:" + error.Message, "警告", MessageBoxButtons.OK, MessageBoxIcon.Error);
}finally{if (reader != null) {
reader.Close();
}
}const string MutexName = "Multithreading";var m = new Mutex(false, MutexName);
}private void richTextBox1_TextChanged(objectsender, EventArgs e) {
}private void Form1_Load(objectsender, EventArgs e) {
System.Windows.Forms.Control.CheckForIllegalCrossThreadCalls= false; //允许其他线程修改
}
}
}
View Code
所以,我感觉线程不是用于这样的东西的,这样的话结果不确定(或者是我太渣渣了)
线程应该是用在那些,计算方面,new一个线程来辅助计算
这个数据,就会显示是写者优先了,尽管我设置了优先级是读者AboveNormal
对了看到java里写,Main线程的优先级是Noraml的。
2 W 1 5
2 W 1 5
2 W 1 5
2 W 1 5
2 W 1 5
2 W 1 5
2 W 1 5
1 R 1 5
View Code
java说,
synchronized可以修饰一个同步一个方法,public synchronized void fun();
同步:就是协同步调,按预定的先后次序进行运行。如:你说完,我再说。
java高级篇P326
一个同步方法在执行之前需要加锁,锁是一种实现资源排他使用的机制。对于实例方法,要给调用该方法的对象加锁。对于静态方法,要给这个类加锁。
但是我不需要对整个类加锁啊,我对静态方法加锁也可以得,???不懂
class myThread implementsRunnable {publicString s;public voidrun() {
System.out.println(s);
}static synchronized voidfun() {
}
}
java的内部类如果需要new一个实体出来,
用name s = new name(); 是不行的。会"is not an enclosing class"
需要Main s = new Main(); 一个实例
然后Main.name bb = s.new name();
有一个问题就是,用lock的话,怎么解决只有一个return的语句呢???
因为lock.lock()之后,还需要lock.unlock()
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;public classMain {static bank bk = newbank();public static voidmain(String[] args) {
ExecutorService ex=Executors.newCachedThreadPool();
ex.execute(newcutMoney());
ex.execute(newaddMoney());
ex.shutdown();
}static classaddMoney implements Runnable {
@Overridepublic voidrun() {while (true) {int val = (int)(Math.random() * 10) + 1;
bk.add(val);try{
Thread.sleep(3000);
}catch(InterruptedException e) {//TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}static classcutMoney implements Runnable {
@Overridepublic voidrun() {while (true) {int val = (int)(Math.random() * 10) + 1;try{while (!bk.cut(val)) {}
}catch(InterruptedException e) {//TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}static classbank {private Lock lock = newReentrantLock();private Condition signal = lock.newCondition();private int money = 0;
bank() {}//synchronized int getMoney() {//只能这样嘛?用lock感觉不行啊//return money;//}
int getMoney() { //只能这样嘛?用lock感觉不行啊
lock.lock();try{returnmoney;
}finally{lock.unlock();
}
}
String getNowTime() {
SimpleDateFormat df= new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//设置日期格式
return (df.format(new Date()));//new Date()为获取当前系统时间
}
boolean cut(intval) throws InterruptedException {lock.lock();try{while (money
System.out.println(getNowTime() + "不够" + val + " " + "现在有" +money);
signal.await(); //等待,不需要一直判判判
}
money-=val;
System.out.println(getNowTime() + "扣除" + val + "钱");
}catch(InterruptedException e) {
}finally{lock.unlock();
}return true;
}void add(intval) {lock.lock();try{
money+=val;
System.out.println(getNowTime() + "转入" + val + "钱");
signal.signalAll();//唤醒
} catch(Exception e) {
e.printStackTrace();
}finally{lock.unlock();
}
}
}
}
减钱加钱
我的方法是:
1、用synchronized
2、try的finally语句是必须进行的