Java - Strange concurrent problems about ReentrantLock - java

I have 2 test cases, while the first one is failed and the second one can successed.
The only difference code is method incr of class Incr.
Why?
public class ReentrantSpinLockTest {
private final Incr incr = new Incr();
#Test
public void lock() throws InterruptedException {
int n = 50;
int inner_loop = 100_000;
CountDownLatch boot = new CountDownLatch(n);
CountDownLatch complete = new CountDownLatch(n);
for (int i = 0; i < n; ++i) {
new Thread(() -> {
try {
boot.await();
for (int k = 0; k < inner_loop; ++k) {
incr.incr();
}
} catch (InterruptedException e) {
throw new RuntimeException(e);
} finally {
complete.countDown();
}
}).start();
boot.countDown();
}
complete.await();
int expect = n * inner_loop;
int actual = incr.getI();
assert expect == actual : String.format("expect %d actual %d", expect, actual);
}
}
The successful Incr:
public class Incr {
private final ReentrantLock lock = new ReentrantLock();
private volatile int i;
// only this diff
public void incr() {
lock.lock();
lock.lock();
i++;
lock.unlock();
lock.unlock();
}
public int getI() {
return i;
}
}
The failed Incr:
public class Incr {
private final ReentrantLock lock = new ReentrantLock();
private volatile int i;
public void incr() {
int k = Math.abs(new Random().nextInt() % 5);
for (int t = 0; t < k; ++t) {
lock.lock();
}
i++;
for (int t = 0; t < k; ++t) {
lock.unlock();
}
}
public int getI() {
return i;
}
}

Related

Where is a problem with this multithreading code?

I want to calculate sum of 2D array with multithreading. But I can't get correct result and programm can't end for some reason.
MatrixService devides task to threads and contains result. (methods getSumma() and setSumma(int summa) are taken from Herbert Schildt)
public class MatrixService {
private boolean valueGet = false;
private int summa;
public int sum(int[][] matrix, int nThreads) {
for (int i = 0; i < nThreads; i++) {
new ColumnSummator(this, matrix, nThreads, i);
}
return summa;
}
public synchronized int getSumma() {
while (valueGet) {
try {
wait();
} catch (InterruptedException e) {
System.out.println(e.getMessage());
}
}
valueGet = true;
notify();
return summa;
}
public synchronized void setSumma(int summa) {
while (!valueGet) {
try {
wait();
} catch (InterruptedException e) {
System.out.println(e.getMessage());
}
}
this.summa = summa;
valueGet = false;
notify();
}
}
ColumnSummator choose columns for sum which this Thread should calculate
import java.util.ArrayList;
import java.util.List;
public class ColumnSummator implements Runnable {
private int summOfColumns;
private final MatrixService matrixService;
private final int[][] matrix;
private final List<Integer> numberColumnsForCount = new ArrayList<>();
public ColumnSummator(MatrixService matrixService, int[][] matrix, int nThreads, int columnSummatorId) {
this.matrixService = matrixService;
this.matrix = matrix;
for (int i = 0; i < matrix[0].length; i++) {
if (i % nThreads == columnSummatorId) {
numberColumnsForCount.add(i);
}
}
new Thread(this).start();
}
#Override
public void run() {
for (int i = 0; i < matrix[0].length; i++) {
if (numberColumnsForCount.contains(i)) {
for (int j = 0; j < matrix.length; j++) {
summOfColumns += matrix[j][i];
}
}
}
matrixService.setSumma(matrixService.getSumma() + summOfColumns);
}
}
And inside main:
public static void main(String[] args) {
MatrixService matrixService = new MatrixService();
int[][] matrix = new int[10][10];
for (int i = 0; i < matrix.length; i++) {
for (int j = 0; j < matrix[0].length; j++) {
matrix[i][j] = (i + 1) * (j + 1);
}
}
int summa = matrixService.sum(matrix, 6);
System.out.println(summa);
}

im going to create two java threads(one thread to multiply numbers another thread to add numbers)

I have to get the output like this:
Here is my code. There are no errors. It starts with PlusThread and prints the first line. Then it will release the lock. After that MultiplyThread starts to run. It will print all the lines instead of notifying the PlusThread.
public class TestThread {
public static void main(String[] args) {
// TODO Auto-generated method stub
Object lock = new Object();
PlusThread pT = new PlusThread(lock, 2, 10);
pT.start();
MultiplyThread mT = new MultiplyThread(lock, 2, 10);
mT.start();
}
}
class PlusThread extends Thread {
Object lock;
int start, range;
public PlusThread(Object lock, int start, int range) {
super();
this.lock = lock;
this.start = start;
this.range = range;
}
#Override
public void run() {
synchronized (this) {
for (int i = start; i <= range; ++i) {
System.out.println(i + " + " + i + " = " + (i + i));
try {
this.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
class MultiplyThread extends Thread {
Object lock;
int start, range;
public MultiplyThread(Object lock, int start, int range) {
this.lock = lock;
this.start = start;
this.range = range;
}
#Override
public void run() {
synchronized (this) {
for (int j = start; j <= range; ++j) {
System.out.println(j + " * " + j + " = " + (j * j));
this.notify();
}
}
}
}
Here is my output:
try this:
public class TestThread {
static Object lock = new Object();
public static void main(String[] args) {
// TODO Auto-generated method stub
PlusThread pT = new PlusThread(lock, 2, 10);
pT.start();
MultiplyThread mT = new MultiplyThread(lock, 2, 10);
mT.start();
}
}
class PlusThread extends Thread {
Object lock;
int start, range;
public PlusThread(Object lock, int start, int range) {
super();
this.lock = lock;
this.start = start;
this.range = range;
}
#Override
public void run() {
synchronized (lock) {
for (int i = start; i <= range; ++i) {
System.out.println(i + " + " + i + " = " + (i + i));
try {
lock.notify();
lock.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
class MultiplyThread extends Thread {
Object lock;
int start, range;
public MultiplyThread(Object lock, int start, int range) {
this.lock = lock;
this.start = start;
this.range = range;
}
#Override
public void run() {
synchronized (lock) {
for (int j = start; j <= range; ++j) {
System.out.println(j + " * " + j + " = " + (j * j));
lock.notify();
try {
lock.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
This will work
static class PlusThread extends Thread {
final Object lock;
int start, range;
public PlusThread(Object lock, int start, int range) {
super();
this.lock = lock;
this.start = start;
this.range = range;
}
#Override
public void run() {
synchronized (lock) {
for (int i = start; i <= range; ++i) {
try {
lock.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(i + " + " + i + " = " + (i + i));
lock.notify();
}
}
}
}
static class MultiplyThread extends Thread {
final Object lock;
int start, range;
public MultiplyThread(Object lock, int start, int range) {
this.lock = lock;
this.start = start;
this.range = range;
}
#Override
public void run() {
synchronized (lock) {
for (int j = start; j <= range; ++j) {
System.out.println(j + " * " + j + " = " + (j * j));
lock.notify();
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}

Unexpected error with my class

When writing a class it is giving me an expected token error and I can not figure out how to solve it or why it is giving it to me.
Here's the code:
public class SetUpDoors {
private int DoorAmount;
private int WinningDoorAmount;
private int[] DoorArray= new int[DoorAmount];
private int winnerSelect = 0;
for (int i = 0; i < DoorAmount; i++) {
if (WinningDoorAmount > 0) {
winnerSelect = (int) Math.round( Math.random());
DoorArray[i] = winnerSelect;
if(winnerSelect == 1) {
WinningDoorAmount--;
}
}
else {
DoorArray[i] = 0;
}
DoorAmount--;
}
void setDoorAmount(int userDoors){
DoorAmount = userDoors;
}
void setWinningDoorAmount(int userWinningDoors) {
WinningDoorAmount = userWinningDoors;
}
}
it is giving the error on the ; at the end of private int winnerSelect = 0;
and an error for the } right below DoorAmount--;
The first is expected token "{" and the second is add "}" to complete block.
You must declare following code inside a method.
For example:
public void newMethod(){
for (int i = 0; i < DoorAmount; i++) {
if (WinningDoorAmount > 0) {
winnerSelect = (int) Math.round( Math.random());
DoorArray[i] = winnerSelect;
if(winnerSelect == 1) {
WinningDoorAmount--;
}
}
}
else {
DoorArray[i] = 0;
}
DoorAmount--;
}
try this
public class SetUpDoors {
private int DoorAmount;
private int WinningDoorAmount;
private int[] DoorArray= new int[DoorAmount];
private int winnerSelect = 0;
{
for (int i = 0; i < DoorAmount; i++) {
if (WinningDoorAmount > 0) {
winnerSelect = (int) Math.round( Math.random());
DoorArray[i] = winnerSelect;
if(winnerSelect == 1) {
WinningDoorAmount--;
}
}
else {
DoorArray[i] = 0;
}
DoorAmount--;
}
}
void setDoorAmount(int userDoors){
DoorAmount = userDoors;
}
void setWinningDoorAmount(int userWinningDoors) {
WinningDoorAmount = userWinningDoors;
}
}

what's wrong with my java(producer-consumer) code?

I wrote this java code with synchronized and busy waiting but I don't know why it doesn't work right! for example I get this output
produced:6
produced:7
consumed:0
consumed:0
how 6 and 7 are produced but 0 is consumed ??? I don't know what's wrong with it,please help me ,here is my code:
package conper;
import java.util.*;
import java.util.concurrent.TimeUnit;
class Queue<Integer> {
int items=0;
int q=0;
public int[] array= new int[10];
Queue(int i) {
}
public boolean isEmpty(){
if (this.q > 0)
{
return false ;
}else{
return true ;}
}
public boolean isFull(){
if (this.q > 10)
{
return true ;
}else{
return false ;
}
}
public int size(){
return items;
}
public synchronized void add(int x){
if(!isFull()){
array[++q]=x;
}
}
public synchronized void remove(int x){
if(!isEmpty()){
array[--q]=x;
}
}
}
class Producer implements Runnable {
private Random random = new Random();
private Queue<Integer> queue;
private boolean working = true;
public Producer(Queue<Integer> q) {
queue = q;
}
public void run() {
int product=0;
int loop = random.nextInt(10) + 20;
for (int i = 0; i < loop; i++) {
double h = Math.pow(2, Math.E * i);
}
while(working){
product = produce();
if(!queue.isFull() ){
break;
}
}
queue.add(product);
System.out.println("produced:"+product);
}
public void stop() {
working = false;
}
private int produce() {
int result = 0;
int loop = random.nextInt(10) + 20;
for (int i = 0; i < loop; i++) {
double h = Math.pow(2, Math.E * i);
}
result = random.nextInt(10);
return result;
}
}
class Consumer implements Runnable {
private Random rnd = new Random();
private Queue<Integer> queue;
private boolean working = true;
public Consumer(Queue<Integer> q) {
queue = q;
}
public void run() {
int product = 0;
while(working){
if(!queue.isEmpty())
break;
}
queue.remove(product);
System.out.println("consumed:"+product);
consume(product);
}
public void stop() {
working = false;
}
public void consume(int product) {
int loop = rnd.nextInt(10000) + 2000;
for (int i = 0; i < loop; i++) {
double h = Math.pow(2, Math.E * i);
}
}
}
public class Main {
public static void main(String[] args) {
Queue<Integer> queue = new Queue<Integer>(5);
Producer p1 = new Producer(queue);
Producer p2 = new Producer(queue);
Consumer c1 = new Consumer(queue);
Consumer c2 = new Consumer(queue);
Thread pt1 = new Thread(p1);
Thread pt2 = new Thread(p2);
Thread ct1 = new Thread(c1);
Thread ct2 = new Thread(c2);
pt1.start();
pt2.start();
ct1.start();
ct2.start();
try {
TimeUnit.MILLISECONDS.sleep(200);
p1.stop();
p2.stop();
c1.stop();
c2.stop();
}
catch (Exception e) {
return;
}
}
}
any suggestion?
Your consumer code reads
int product = 0;
// code which doesn't change "product"
System.out.println("consumed:"+product);
I suggest you need a remove() method which returns the value from the queue instead of being passed a value.
I also suggest you get the code to work in one thread before attempting to use in multiple threads.

"A Java Exception has occurred"

So I'm trying to run my pacman project as a jar(also tried runnable) and I just get the error message you see in the title. It runs perfectly fine in eclipse/netbeans, but whilst cleaning/building i see the warnings:
Note: C:\Users\Lucas\Documents\Eclipse\PackMan\src\game\packman\GameData.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
The main class is correct and assigned. Does anybody know what I'm doing wrong?
Here is my GameData class
public class GameData {
int mazeNo;
CopyOnWriteArrayList<Position> pills;
CopyOnWriteArrayList<Position> powerPills;
public MoverInfo packman;
public GhostInfo[] ghostInfos = new GhostInfo[4];
public int score;
Maze[] mazes;
boolean dead = false;
boolean win = false;
public GameData() {
mazes = new Maze[4];
// load mazes information
for (int m=0; m<4; m++) {
mazes[m] = new Maze(m);
}
setMaze(mazeNo);
}
private void setMaze(int m) {
packman = new MoverInfo(mazes[m].packmanPos);
for (int g=0; g<4; g++) {
ghostInfos[g] = new GhostInfo(mazes[m].ghostPos);
}
pills = new CopyOnWriteArrayList((List<Position>)(mazes[m].pills.clone()));
powerPills = new CopyOnWriteArrayList((List<Position>)(mazes[m].powerPills.clone()));
}
public void movePackMan(int reqDir) {
if (move(reqDir, packman)) {
packman.curDir = reqDir;
} else {
move(packman.curDir, packman);
}
}
private int wrap(int value, int incre, int max) {
return (value+max+incre)%max;
}
private boolean move(int reqDir, MoverInfo info) {
// current position of packman is (row, column)
int row = info.pos.row;
int column = info.pos.column;
int rows = mazes[mazeNo].rows;
int columns = mazes[mazeNo].columns;
int nrow = wrap(row, MoverInfo.DROW[reqDir], rows);
int ncol = wrap(column, MoverInfo.DCOL[reqDir], columns);
if (mazes[mazeNo].charAt(nrow, ncol) != '0') {
info.pos.row = nrow;
info.pos.column = ncol;
return true;
}
return false;
}
public void update() {
if (pills.contains(packman.pos)) {
pills.remove(packman.pos);
score += 5;
} else if (powerPills.contains(packman.pos)) {
powerPills.remove(packman.pos);
score += 50;
for (GhostInfo g:ghostInfos) {
g.edibleCountDown = 500;
}
}
for (GhostInfo g:ghostInfos) {
if (g.edibleCountDown > 0) {
if (touching(g.pos, packman.pos)) {
// eat the ghost and reset
score += 100;
g.curDir = g.reqDir = MoverInfo.LEFT;
g.pos.row = mazes[mazeNo].ghostPos.row;
g.pos.column = mazes[mazeNo].ghostPos.column;
g.edibleCountDown = 0;
}
g.edibleCountDown--;
} else {
if (touching(g.pos, packman.pos)) {
dead = true;
}
}
}
// level is cleared
if (pills.isEmpty() && powerPills.isEmpty()) {
mazeNo++;
if (mazeNo < 4) {
setMaze(mazeNo);
} else if (mazeNo == 5) {
win = true;
} else {
// game over
dead = true;
}
}
}
private boolean touching(Position a, Position b) {
return Math.abs(a.row-b.row) + Math.abs(a.column-b.column) < 3;
}
public void moveGhosts(int[] reqDirs) {
for (int i=0; i<4; i++) {
GhostInfo info = ghostInfos[i];
info.reqDir = reqDirs[i];
if (move(info.reqDir, info)) {
info.curDir = info.reqDir;
} else {
move(info.curDir, info);
}
}
}
public int getWidth() {
return mazes[mazeNo].width;
}
public int getHeight() {
return mazes[mazeNo].height;
}
public List<Integer> getPossibleDirs(Position pos) {
List<Integer> list = new ArrayList<>();
for (int d=0; d<4;d++) {
Position npos = getNextPositionInDir(pos, d);
if (mazes[mazeNo].charAt(npos.row, npos.column) != '0') {
list.add(d);
}
}
return list;
}
private Position getNextPositionInDir(Position pos, int d) {
int nrow = wrap(pos.row, MoverInfo.DROW[d], mazes[mazeNo].rows);
int ncol = wrap(pos.column, MoverInfo.DCOL[d], mazes[mazeNo].columns);
return new Position(nrow, ncol);
}
}

Categories

Resources