Race between procedural Blocks and always block triggering itself

module test;
  task foo (ref bit[3:0] a1, ref bit[3:0] out_a3);
  $display(“[task]Start of TAsk a1= %d at time = %0t”,a1, $time);
  #2 a1=5;
  $display(“[task] al changed to=%0d at time=%0t”,a1, $time); 
  #2 out_a3 = a1+3;
  #1
  $display (“Ltask End of task al=%0d out_a3=%0d at time-%0t”, a1, out_a3, $time);
endtask
//end of time 7
bit [3:0] i1, out;

initial begin
  i1=0; out=0;
  foo(i1,out);
  $display("[test] i1=%0d out=%0d at time=%0t ",i1,out,$time);
end
 always @(i1) begin
    $display(“[Always_i1] Detected change on i1=%0d at time=%0t”, i1,$time);
    i1++;
  end

  always @(out)
    $display(“[Always_out]Detected change on out=%0d at time=%0t”, out, $time);

endmodule

From the above code we are getting output as below :

[task]Start of TAsk a1=  0 at time = 0
[task] al changed to=5 at time=2
[Always_i1] Detected change on i1=5 at time=2
[Always_out]Detected change on out=9 at time=4
Ltask End of task al=6 out_a3=9 at time-5
[test] i1=6 out=9 at time=5

My question here is when we got enter to the always blk we can’t struck there contionously as i incrementing (i++), And is there any race happening between all procedural blks and why compiler not triggering always blk when we intialize i1 with 0.